Re: [RFC PATCH 1/3] drm: Add support for Amlogic Meson Graphic Controller

From: Daniel Vetter
Date: Mon Nov 28 2016 - 03:16:19 EST


On Fri, Nov 25, 2016 at 05:03:09PM +0100, Neil Armstrong wrote:
> The Amlogic Meson Display controller is composed of several components :
>
> DMC|---------------VPU (Video Processing Unit)----------------|------HHI------|
> | vd1 _______ _____________ _________________ | |
> D |-------| |----| | | | | HDMI PLL |
> D | vd2 | VIU | | Video Post | | Video Encoders |<---|-----VCLK |
> R |-------| |----| Processing | | | | |
> | osd2 | | | |---| Enci ----------|----|-----VDAC------|
> R |-------| CSC |----| Scalers | | Encp ----------|----|----HDMI-TX----|
> A | osd1 | | | Blenders | | Encl ----------|----|---------------|
> M |-------|______|----|____________| |________________| | |
> ___|__________________________________________________________|_______________|
>
>
> VIU: Video Input Unit
> ---------------------
>
> The Video Input Unit is in charge of the pixel scanout from the DDR memory.
> It fetches the frames addresses, stride and parameters from the "Canvas" memory.
> This part is also in charge of the CSC (Colorspace Conversion).
> It can handle 2 OSD Planes and 2 Video Planes.
>
> VPP: Video Processing Unit
> --------------------------
>
> The Video Processing Unit is in charge if the scaling and blending of the
> various planes into a single pixel stream.
> There is a special "pre-blending" used by the video planes with a dedicated
> scaler and a "post-blending" to merge with the OSD Planes.
> The OSD planes also have a dedicated scaler for one of the OSD.
>
> VENC: Video Encoders
> --------------------
>
> The VENC is composed of the multiple pixel encoders :
> - ENCI : Interlace Video encoder for CVBS and Interlace HDMI
> - ENCP : Progressive Video Encoder for HDMI
> - ENCL : LCD LVDS Encoder
> The VENC Unit gets a Pixel Clocks (VCLK) from a dedicated HDMI PLL and clock
> tree and provides the scanout clock to the VPP and VIU.
> The ENCI is connected to a single VDAC for Composite Output.
> The ENCI and ENCP are connected to an on-chip HDMI Transceiver.
>
> This driver is a DRM/KMS driver using the following DRM components :
> - GEM-CMA
> - PRIME-CMA
> - Atomic Modesetting
> - FBDev-CMA
>
> For the following SoCs :
> - GXBB Family (S905)
> - GXL Family (S905X, S905D)
> - GXM Family (S912)
>
> The current driver only supports the CVBS PAL/NTSC output modes, but the
> CRTC/Planes management should support bigger modes.
> But Advanced Colorspace Conversion, Scaling and HDMI Modes will be added in
> a second time.
>
> The Device Tree bindings makes use of the endpoints video interface definitions
> to connect to the optional CVBS and in the future the HDMI Connector nodes.
>
> HDMI Support is planned for a next release.
>
> Signed-off-by: Neil Armstrong <narmstrong@xxxxxxxxxxxx>

Few small comments below, but looks reasonable overall. Once you have acks
for the DT part pls submit the entire series as a pull request to Dave
Airlie (with an additional patch to add a MAINTAINERS entry).

Cheers, Daniel

> ---
> drivers/gpu/drm/Kconfig | 2 +
> drivers/gpu/drm/Makefile | 1 +
> drivers/gpu/drm/meson/Kconfig | 8 +
> drivers/gpu/drm/meson/Makefile | 5 +
> drivers/gpu/drm/meson/meson_canvas.c | 96 +++
> drivers/gpu/drm/meson/meson_canvas.h | 31 +
> drivers/gpu/drm/meson/meson_crtc.c | 176 ++++
> drivers/gpu/drm/meson/meson_crtc.h | 34 +
> drivers/gpu/drm/meson/meson_cvbs.c | 293 +++++++
> drivers/gpu/drm/meson/meson_cvbs.h | 32 +
> drivers/gpu/drm/meson/meson_drv.c | 383 +++++++++
> drivers/gpu/drm/meson/meson_drv.h | 68 ++
> drivers/gpu/drm/meson/meson_plane.c | 150 ++++
> drivers/gpu/drm/meson/meson_plane.h | 32 +
> drivers/gpu/drm/meson/meson_registers.h | 1395 +++++++++++++++++++++++++++++++
> drivers/gpu/drm/meson/meson_vclk.c | 169 ++++
> drivers/gpu/drm/meson/meson_vclk.h | 36 +
> drivers/gpu/drm/meson/meson_venc.c | 286 +++++++
> drivers/gpu/drm/meson/meson_venc.h | 77 ++
> drivers/gpu/drm/meson/meson_viu.c | 497 +++++++++++
> drivers/gpu/drm/meson/meson_viu.h | 37 +
> drivers/gpu/drm/meson/meson_vpp.c | 189 +++++
> drivers/gpu/drm/meson/meson_vpp.h | 43 +
> 23 files changed, 4040 insertions(+)
> create mode 100644 drivers/gpu/drm/meson/Kconfig
> create mode 100644 drivers/gpu/drm/meson/Makefile
> create mode 100644 drivers/gpu/drm/meson/meson_canvas.c
> create mode 100644 drivers/gpu/drm/meson/meson_canvas.h
> create mode 100644 drivers/gpu/drm/meson/meson_crtc.c
> create mode 100644 drivers/gpu/drm/meson/meson_crtc.h
> create mode 100644 drivers/gpu/drm/meson/meson_cvbs.c
> create mode 100644 drivers/gpu/drm/meson/meson_cvbs.h
> create mode 100644 drivers/gpu/drm/meson/meson_drv.c
> create mode 100644 drivers/gpu/drm/meson/meson_drv.h
> create mode 100644 drivers/gpu/drm/meson/meson_plane.c
> create mode 100644 drivers/gpu/drm/meson/meson_plane.h
> create mode 100644 drivers/gpu/drm/meson/meson_registers.h
> create mode 100644 drivers/gpu/drm/meson/meson_vclk.c
> create mode 100644 drivers/gpu/drm/meson/meson_vclk.h
> create mode 100644 drivers/gpu/drm/meson/meson_venc.c
> create mode 100644 drivers/gpu/drm/meson/meson_venc.h
> create mode 100644 drivers/gpu/drm/meson/meson_viu.c
> create mode 100644 drivers/gpu/drm/meson/meson_viu.h
> create mode 100644 drivers/gpu/drm/meson/meson_vpp.c
> create mode 100644 drivers/gpu/drm/meson/meson_vpp.h
>
> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> index 483059a..344ced6 100644
> --- a/drivers/gpu/drm/Kconfig
> +++ b/drivers/gpu/drm/Kconfig
> @@ -223,6 +223,8 @@ source "drivers/gpu/drm/hisilicon/Kconfig"
>
> source "drivers/gpu/drm/mediatek/Kconfig"
>
> +source "drivers/gpu/drm/meson/Kconfig"
> +
> # Keep legacy drivers last
>
> menuconfig DRM_LEGACY
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index 25c7204..47e7c45 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -79,6 +79,7 @@ obj-$(CONFIG_DRM_TEGRA) += tegra/
> obj-$(CONFIG_DRM_STI) += sti/
> obj-$(CONFIG_DRM_IMX) += imx/
> obj-$(CONFIG_DRM_MEDIATEK) += mediatek/
> +obj-$(CONFIG_DRM_MESON) += meson/
> obj-y += i2c/
> obj-y += panel/
> obj-y += bridge/
> diff --git a/drivers/gpu/drm/meson/Kconfig b/drivers/gpu/drm/meson/Kconfig
> new file mode 100644
> index 0000000..8e5aa22
> --- /dev/null
> +++ b/drivers/gpu/drm/meson/Kconfig
> @@ -0,0 +1,8 @@
> +config DRM_MESON
> + tristate "DRM Support for Amlogic Meson Display Controller"
> + depends on DRM && OF && (ARM || ARM64)
> + select DRM_KMS_HELPER
> + select DRM_KMS_CMA_HELPER
> + select DRM_GEM_CMA_HELPER
> + select VIDEOMODE_HELPERS
> + select REGMAP_MMIO
> diff --git a/drivers/gpu/drm/meson/Makefile b/drivers/gpu/drm/meson/Makefile
> new file mode 100644
> index 0000000..ab1abfa
> --- /dev/null
> +++ b/drivers/gpu/drm/meson/Makefile
> @@ -0,0 +1,5 @@
> +meson-y := meson_drv.o meson_plane.o meson_crtc.o
> +meson-y += meson_viu.o meson_vpp.o meson_venc.o meson_vclk.o meson_canvas.o
> +
> +obj-$(CONFIG_DRM_MESON) += meson.o
> +obj-$(CONFIG_DRM_MESON) += meson_cvbs.o
> diff --git a/drivers/gpu/drm/meson/meson_canvas.c b/drivers/gpu/drm/meson/meson_canvas.c
> new file mode 100644
> index 0000000..fe4f50f
> --- /dev/null
> +++ b/drivers/gpu/drm/meson/meson_canvas.c
> @@ -0,0 +1,96 @@
> +/*
> + * Copyright (C) 2016 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong@xxxxxxxxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
> + * 02111-1307, USA.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <drm/drmP.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include "meson_drv.h"
> +#include "meson_canvas.h"
> +#include "meson_registers.h"
> +
> +/*
> + * CANVAS is a memory zone where physical memory frames information
> + * are stored for the VIU to scanout.
> + */
> +
> +/* DMC Registers */
> +#define DMC_CAV_LUT_DATAL 0x48 /* 0x12 offset in data sheet */
> +#define CANVAS_WIDTH_LBIT 29
> +#define CANVAS_WIDTH_LWID 3
> +#define DMC_CAV_LUT_DATAH 0x4c /* 0x13 offset in data sheet */
> +#define CANVAS_WIDTH_HBIT 0
> +#define CANVAS_HEIGHT_BIT 9
> +#define CANVAS_BLKMODE_BIT 24
> +#define DMC_CAV_LUT_ADDR 0x50 /* 0x14 offset in data sheet */
> +#define CANVAS_LUT_WR_EN (0x2 << 8)
> +#define CANVAS_LUT_RD_EN (0x1 << 8)
> +
> +/* Canvas configuration. */
> +#define MESON_CANVAS_WRAP_NONE 0x00
> +#define MESON_CANVAS_WRAP_X 0x01
> +#define MESON_CANVAS_WRAP_Y 0x02
> +
> +#define MESON_CANVAS_BLKMODE_LINEAR 0x00
> +#define MESON_CANVAS_BLKMODE_32x32 0x01
> +#define MESON_CANVAS_BLKMODE_64x64 0x02
> +
> +static void meson_canvas_setup(struct meson_drm *priv,
> + uint32_t canvas_index, uint32_t addr,
> + uint32_t stride, uint32_t height,
> + unsigned int wrap,
> + unsigned int blkmode)
> +{
> + unsigned int val;
> +
> + regmap_write(priv->dmc, DMC_CAV_LUT_DATAL,
> + (((addr + 7) >> 3)) |
> + (((stride + 7) >> 3) << CANVAS_WIDTH_LBIT));
> +
> + regmap_write(priv->dmc, DMC_CAV_LUT_DATAH,
> + ((((stride + 7) >> 3) >> CANVAS_WIDTH_LWID) <<
> + CANVAS_WIDTH_HBIT) |
> + (height << CANVAS_HEIGHT_BIT) |
> + (wrap << 22) |
> + (blkmode << CANVAS_BLKMODE_BIT));
> +
> + regmap_write(priv->dmc, DMC_CAV_LUT_ADDR,
> + CANVAS_LUT_WR_EN | canvas_index);
> +
> + /* Force a read-back to make sure everything is flushed. */
> + regmap_read(priv->dmc, DMC_CAV_LUT_DATAH, &val);
> +}
> +
> +void meson_canvas_update_osd1_buffer(struct meson_drm *priv,
> + struct drm_plane *plane)
> +{
> + struct drm_plane_state *state = plane->state;
> + struct drm_framebuffer *fb = state->fb;
> + struct drm_gem_cma_object *gem;
> +
> + gem = drm_fb_cma_get_gem_obj(fb, 0);
> +
> + /* Swap out the OSD canvas with the new addr. */
> + meson_canvas_setup(priv, MESON_CANVAS_ID_OSD1,
> + gem->paddr, fb->pitches[0],
> + fb->height, MESON_CANVAS_WRAP_NONE,
> + MESON_CANVAS_BLKMODE_LINEAR);
> +}
> diff --git a/drivers/gpu/drm/meson/meson_canvas.h b/drivers/gpu/drm/meson/meson_canvas.h
> new file mode 100644
> index 0000000..542f615
> --- /dev/null
> +++ b/drivers/gpu/drm/meson/meson_canvas.h
> @@ -0,0 +1,31 @@
> +/*
> + * Copyright (C) 2016 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong@xxxxxxxxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
> + * 02111-1307, USA.
> + */
> +
> +/* Canvas LUT Memory */
> +
> +#ifndef __MESON_CANVAS_H
> +#define __MESON_CANVAS_H
> +
> +#define MESON_CANVAS_ID_OSD1 0x4e
> +
> +void meson_canvas_update_osd1_buffer(struct meson_drm *priv,
> + struct drm_plane *plane);
> +
> +#endif /* __MESON_VIU_H */
> diff --git a/drivers/gpu/drm/meson/meson_crtc.c b/drivers/gpu/drm/meson/meson_crtc.c
> new file mode 100644
> index 0000000..d0bf04b
> --- /dev/null
> +++ b/drivers/gpu/drm/meson/meson_crtc.c
> @@ -0,0 +1,176 @@
> +/*
> + * Copyright (C) 2016 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong@xxxxxxxxxxxx>
> + * Copyright (C) 2014 Endless Mobile
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
> + * 02111-1307, USA.
> + *
> + * Written by:
> + * Jasper St. Pierre <jstpierre@xxxxxxxxxxx>
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/platform_device.h>
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_flip_work.h>
> +#include <drm/drm_crtc_helper.h>
> +
> +#include "meson_crtc.h"
> +#include "meson_plane.h"
> +#include "meson_vpp.h"
> +#include "meson_viu.h"
> +#include "meson_venc.h"
> +
> +/* CRTC definition */
> +
> +struct meson_crtc {
> + struct drm_crtc base;
> + struct drm_pending_vblank_event *event;
> + struct meson_drm *priv;
> +};
> +#define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
> +
> +/* CRTC */
> +
> +static const struct drm_crtc_funcs meson_crtc_funcs = {
> + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
> + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> + .destroy = drm_crtc_cleanup,
> + .page_flip = drm_atomic_helper_page_flip,
> + .reset = drm_atomic_helper_crtc_reset,
> + .set_config = drm_atomic_helper_set_config,
> +};
> +
> +static void meson_crtc_enable(struct drm_crtc *crtc)
> +{
> + struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
> + struct drm_plane *plane = meson_crtc->priv->primary_plane;
> +
> + meson_vpp_enable_postblend(meson_crtc->priv, plane->state->crtc_w);
> +
> + meson_crtc->priv->viu.osd1_enabled = true;
> +}
> +
> +static void meson_crtc_disable(struct drm_crtc *crtc)
> +{
> + struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
> +
> + meson_crtc->priv->viu.osd1_enabled = false;
> +
> + meson_vpp_disable_postblend(meson_crtc->priv);
> +
> + if (crtc->state->event && !crtc->state->active) {
> + spin_lock_irq(&crtc->dev->event_lock);
> + drm_crtc_send_vblank_event(crtc, crtc->state->event);
> + spin_unlock_irq(&crtc->dev->event_lock);
> +
> + crtc->state->event = NULL;
> + }
> +}
> +
> +static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
> + struct drm_crtc_state *state)
> +{
> + struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
> + unsigned long flags;
> +
> + if (crtc->state->event) {
> + WARN_ON(drm_crtc_vblank_get(crtc) != 0);
> +
> + spin_lock_irqsave(&crtc->dev->event_lock, flags);
> + meson_crtc->event = crtc->state->event;
> + spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
> + crtc->state->event = NULL;

If you set this to NULL here
> + }
> +}
> +
> +static void meson_crtc_atomic_flush(struct drm_crtc *crtc,
> + struct drm_crtc_state *old_crtc_state)
> +{
> + struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
> + struct drm_pending_vblank_event *event = crtc->state->event;
> +
> + if (meson_crtc->priv->viu.osd1_enabled)
> + meson_crtc->priv->viu.osd1_commit = true;
> +
> + if (event) {
> + crtc->state->event = NULL;
> +
> + spin_lock_irq(&crtc->dev->event_lock);
> + if (drm_crtc_vblank_get(crtc) == 0)
> + drm_crtc_arm_vblank_event(crtc, event);
> + else
> + drm_crtc_send_vblank_event(crtc, event);
> + spin_unlock_irq(&crtc->dev->event_lock);
> + }

This here becomes dead code. And indeed it is, since you have your own
special crtc/vblank irq handling code right below. Please remove to avoid
confusion.

> +}
> +
> +static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs = {
> + .enable = meson_crtc_enable,
> + .disable = meson_crtc_disable,
> + .atomic_begin = meson_crtc_atomic_begin,
> + .atomic_flush = meson_crtc_atomic_flush,
> +};
> +
> +void meson_crtc_irq(struct meson_drm *priv)
> +{
> + struct meson_crtc *meson_crtc = to_meson_crtc(priv->crtc);
> + unsigned long flags;
> +
> + meson_viu_sync_osd1(priv);
> +
> + drm_crtc_handle_vblank(priv->crtc);
> +
> + spin_lock_irqsave(&priv->drm->event_lock, flags);
> + if (meson_crtc->event) {
> + drm_crtc_send_vblank_event(priv->crtc, meson_crtc->event);
> + drm_crtc_vblank_put(priv->crtc);
> + meson_crtc->event = NULL;
> + }
> + spin_unlock_irqrestore(&priv->drm->event_lock, flags);
> +}
> +
> +int meson_crtc_create(struct meson_drm *priv)
> +{
> + struct meson_crtc *meson_crtc;
> + struct drm_crtc *crtc;
> + int ret;
> +
> + meson_crtc = devm_kzalloc(priv->drm->dev, sizeof(*meson_crtc),
> + GFP_KERNEL);
> + if (!meson_crtc)
> + return -ENOMEM;
> +
> + meson_crtc->priv = priv;
> + crtc = &meson_crtc->base;
> + ret = drm_crtc_init_with_planes(priv->drm, crtc,
> + priv->primary_plane, NULL,
> + &meson_crtc_funcs, "meson_crtc");
> + if (ret) {
> + dev_err(priv->drm->dev, "Failed to init CRTC\n");
> + return ret;
> + }
> +
> + drm_crtc_helper_add(crtc, &meson_crtc_helper_funcs);
> +
> + priv->crtc = crtc;
> +
> + return 0;
> +}
> diff --git a/drivers/gpu/drm/meson/meson_crtc.h b/drivers/gpu/drm/meson/meson_crtc.h
> new file mode 100644
> index 0000000..9f0c20b
> --- /dev/null
> +++ b/drivers/gpu/drm/meson/meson_crtc.h
> @@ -0,0 +1,34 @@
> +/*
> + * Copyright (C) 2016 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong@xxxxxxxxxxxx>
> + * Copyright (C) 2014 Endless Mobile
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
> + * 02111-1307, USA.
> + *
> + * Written by:
> + * Jasper St. Pierre <jstpierre@xxxxxxxxxxx>
> + */
> +
> +#ifndef __MESON_CRTC_H
> +#define __MESON_CRTC_H
> +
> +#include "meson_drv.h"
> +
> +int meson_crtc_create(struct meson_drm *priv);
> +
> +void meson_crtc_irq(struct meson_drm *priv);
> +
> +#endif /* __MESON_CRTC_H */
> diff --git a/drivers/gpu/drm/meson/meson_cvbs.c b/drivers/gpu/drm/meson/meson_cvbs.c
> new file mode 100644
> index 0000000..d5f2441
> --- /dev/null
> +++ b/drivers/gpu/drm/meson/meson_cvbs.c
> @@ -0,0 +1,293 @@
> +/*
> + * Copyright (C) 2016 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong@xxxxxxxxxxxx>
> + * Copyright (C) 2014 Endless Mobile
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
> + * 02111-1307, USA.
> + *
> + * Written by:
> + * Jasper St. Pierre <jstpierre@xxxxxxxxxxx>
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/component.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_edid.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_atomic_helper.h>
> +
> +#include "meson_cvbs.h"
> +#include "meson_venc.h"
> +
> +struct meson_cvbs_mode {
> + struct meson_cvbs_enci_mode *enci;
> + struct drm_display_mode mode;
> +};
> +struct meson_cvbs {
> + struct drm_connector connector;
> + struct drm_encoder encoder;
> + struct meson_drm *priv;
> + struct meson_cvbs_mode *mode;
> +};
> +#define connector_to_meson_cvbs(x) \
> + container_of(x, struct meson_cvbs, connector)
> +#define encoder_to_meson_cvbs(x) \
> + container_of(x, struct meson_cvbs, encoder)
> +
> +/* Supported Modes */
> +
> +struct meson_cvbs_mode meson_cvbs_modes[] = {
> + { /* PAL */
> + .enci = &meson_cvbs_enci_pal,
> + .mode = {
> + DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 13500,
> + 720, 732, 795, 864, 0, 576, 580, 586, 625, 0,
> + DRM_MODE_FLAG_INTERLACE),
> + .vrefresh = 50,
> + .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3,
> + },
> + },
> + { /* NTSC */
> + .enci = &meson_cvbs_enci_ntsc,
> + .mode = {
> + DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 13500,
> + 720, 739, 801, 858, 0, 480, 488, 494, 525, 0,
> + DRM_MODE_FLAG_INTERLACE),
> + .vrefresh = 60,
> + .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3,
> + },
> + },
> +};
> +
> +/* Encoder */
> +
> +static void meson_cvbs_encoder_destroy(struct drm_encoder *encoder)
> +{
> + drm_encoder_cleanup(encoder);
> +}
> +
> +static const struct drm_encoder_funcs meson_cvbs_encoder_funcs = {
> + .destroy = meson_cvbs_encoder_destroy,
> +};
> +
> +static int meson_cvbs_encoder_atomic_check(struct drm_encoder *encoder,
> + struct drm_crtc_state *crtc_state,
> + struct drm_connector_state *conn_state)
> +{
> + return 0;
> +}

Dummy atomic_check isn't needed, pls remove.

> +
> +static void meson_cvbs_encoder_disable(struct drm_encoder *encoder)
> +{
> + struct meson_cvbs *meson_cvbs = encoder_to_meson_cvbs(encoder);
> +
> + meson_venci_cvbs_disable(meson_cvbs->priv);
> +}
> +
> +static void meson_cvbs_encoder_enable(struct drm_encoder *encoder)
> +{
> + struct meson_cvbs *meson_cvbs = encoder_to_meson_cvbs(encoder);
> +
> + meson_venci_cvbs_enable(meson_cvbs->priv);
> +}

Personally I'd remove the indirection above, more direct code is easier to
read.

> +
> +static void meson_cvbs_encoder_mode_set(struct drm_encoder *encoder,
> + struct drm_display_mode *mode,
> + struct drm_display_mode *adjusted_mode)
> +{
> + struct meson_cvbs *meson_cvbs = encoder_to_meson_cvbs(encoder);
> + int i;
> +
> + drm_mode_debug_printmodeline(mode);
> +
> + for (i = 0; i < ARRAY_SIZE(meson_cvbs_modes); ++i) {
> + struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
> +
> + if (drm_mode_equal(mode, &meson_mode->mode)) {
> + meson_cvbs->mode = meson_mode;
> +
> + meson_venci_cvbs_mode_set(meson_cvbs->priv,
> + meson_mode->enci);
> + break;
> + }
> + }
> +}

What happens if userspace sets a mode you don't have? I guess you do need
a real atomic_check, so you can return -EINVAL if that's the case ;-)

> +
> +static const struct drm_encoder_helper_funcs meson_cvbs_encoder_helper_funcs = {
> + .atomic_check = meson_cvbs_encoder_atomic_check,
> + .disable = meson_cvbs_encoder_disable,
> + .enable = meson_cvbs_encoder_enable,
> + .mode_set = meson_cvbs_encoder_mode_set,
> +};
> +
> +/* Connector */
> +
> +static void meson_cvbs_connector_destroy(struct drm_connector *connector)
> +{
> + drm_connector_cleanup(connector);
> +}
> +
> +static enum drm_connector_status
> +meson_cvbs_connector_detect(struct drm_connector *connector, bool force)
> +{

FIXME: Implement load-detect?

> + return connector_status_connected;
> +}
> +
> +static int meson_cvbs_connector_get_modes(struct drm_connector *connector)
> +{
> + struct drm_device *dev = connector->dev;
> + struct drm_display_mode *mode;
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(meson_cvbs_modes); ++i) {
> + struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
> +
> + mode = drm_mode_duplicate(dev, &meson_mode->mode);
> + if (!mode) {
> + DRM_ERROR("Failed to create a new display mode\n");
> + return 0;
> + }
> +
> + drm_mode_probed_add(connector, mode);
> + }
> +
> + return i;
> +}
> +
> +static int meson_cvbs_connector_mode_valid(struct drm_connector *connector,
> + struct drm_display_mode *mode)
> +{
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(meson_cvbs_modes); ++i) {
> + struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
> +
> + if (drm_mode_equal(mode, &meson_mode->mode))
> + return MODE_OK;
> + }
> +
> + return MODE_BAD;
> +}

Ok, this is confusion, but I thought the docs explain this. mode_valid is
only to validate the modes added in get_modes. This is useful for outputs
which add modes from an EDID, but not in this case. Having a mode_valid
unfortunately doesn't ensure that these modes will be rejected in a
modeset, for that you need a separate mode_fixup or atomic_check on the
encoder.

It's a bit a long-standing issue, but not entirely non-trivial to fix up:
In the general case the atomic_check is for a specific configuration,
whereaas mode_valid must only filter modes that won't work in any
configuration. For display blocks with lots of shared resources there's a
big difference between the two.

Please double-check the kerneldoc for all these hooks, and if this is not
clearly enough explained for you then pls raise this (or even better,
submit at patch).

> +
> +static const struct drm_connector_funcs meson_cvbs_connector_funcs = {
> + .dpms = drm_atomic_helper_connector_dpms,
> + .detect = meson_cvbs_connector_detect,
> + .fill_modes = drm_helper_probe_single_connector_modes,
> + .destroy = meson_cvbs_connector_destroy,
> + .reset = drm_atomic_helper_connector_reset,
> + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static const
> +struct drm_connector_helper_funcs meson_cvbs_connector_helper_funcs = {
> + .get_modes = meson_cvbs_connector_get_modes,
> + .mode_valid = meson_cvbs_connector_mode_valid,
> +};
> +
> +static int meson_cvbs_bind(struct device *dev, struct device *master,
> + void *data)
> +{
> + struct drm_device *drm = data;
> + struct meson_drm *priv = drm->dev_private;
> + struct meson_cvbs *meson_cvbs;
> + struct drm_connector *connector;
> + struct drm_encoder *encoder;
> + int ret;
> +
> + meson_cvbs = devm_kzalloc(dev, sizeof(*meson_cvbs), GFP_KERNEL);
> + if (!meson_cvbs)
> + return -ENOMEM;
> +
> + meson_cvbs->priv = priv;
> + connector = &meson_cvbs->connector;
> + encoder = &meson_cvbs->encoder;
> +
> + /* Encoder */
> +
> + drm_encoder_helper_add(encoder, &meson_cvbs_encoder_helper_funcs);
> +
> + ret = drm_encoder_init(drm, encoder, &meson_cvbs_encoder_funcs,
> + DRM_MODE_ENCODER_TVDAC, "meson_cvbs");
> + if (ret) {
> + dev_err(dev, "Failed to init CVBS encoder\n");
> + return ret;
> + }
> +
> + encoder->possible_crtcs = BIT(0);
> +
> + /* Connector */
> +
> + drm_connector_helper_add(connector,
> + &meson_cvbs_connector_helper_funcs);
> +
> + drm_connector_init(drm, connector, &meson_cvbs_connector_funcs,
> + DRM_MODE_CONNECTOR_Composite);
> + if (ret) {
> + dev_err(dev, "Failed to init CVBS connector\n");
> + return ret;
> + }
> +
> + connector->interlace_allowed = 1;
> +
> + drm_mode_connector_attach_encoder(connector, encoder);
> +
> + return 0;
> +}
> +
> +static void meson_cvbs_unbind(struct device *dev, struct device *master,
> + void *data)
> +{
> + /* Nothing to do yet */
> +}
> +
> +static const struct component_ops meson_cvbs_ops = {
> + .bind = meson_cvbs_bind,
> + .unbind = meson_cvbs_unbind,
> +};
> +
> +static int meson_cvbs_probe(struct platform_device *pdev)
> +{
> + return component_add(&pdev->dev, &meson_cvbs_ops);
> +}
> +
> +static int meson_cvbs_remove(struct platform_device *pdev)
> +{
> + component_del(&pdev->dev, &meson_cvbs_ops);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id meson_cvbs_of_table[] = {
> + { .compatible = "amlogic,meson-gx-venc-cvbs" },
> + { .compatible = "amlogic,meson-gxl-venc-cvbs" },
> + { .compatible = "amlogic,meson-gxm-venc-cvbs" },
> + { .compatible = "amlogic,meson-gxbb-venc-cvbs" },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, meson_cvbs_of_table);
> +
> +static struct platform_driver meson_cvbs_platform_driver = {
> + .probe = meson_cvbs_probe,
> + .remove = meson_cvbs_remove,
> + .driver = {
> + .name = "meson-cvbs",
> + .of_match_table = meson_cvbs_of_table,
> + },
> +};
> +module_platform_driver(meson_cvbs_platform_driver);
> diff --git a/drivers/gpu/drm/meson/meson_cvbs.h b/drivers/gpu/drm/meson/meson_cvbs.h
> new file mode 100644
> index 0000000..6d5ade7
> --- /dev/null
> +++ b/drivers/gpu/drm/meson/meson_cvbs.h
> @@ -0,0 +1,32 @@
> +/*
> + * Copyright (C) 2016 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong@xxxxxxxxxxxx>
> + * Copyright (C) 2014 Endless Mobile
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
> + * 02111-1307, USA.
> + *
> + * Written by:
> + * Jasper St. Pierre <jstpierre@xxxxxxxxxxx>
> + */
> +
> +#ifndef __MESON_CVBS_H
> +#define __MESON_CVBS_H
> +
> +#include "meson_drv.h"
> +
> +int meson_cvbs_create(struct meson_drm *priv);
> +
> +#endif /* __MESON_CVBS_H */
> diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
> new file mode 100644
> index 0000000..8b4a5bf
> --- /dev/null
> +++ b/drivers/gpu/drm/meson/meson_drv.c
> @@ -0,0 +1,383 @@
> +/*
> + * Copyright (C) 2016 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong@xxxxxxxxxxxx>
> + * Copyright (C) 2014 Endless Mobile
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
> + * 02111-1307, USA.
> + *
> + * Written by:
> + * Jasper St. Pierre <jstpierre@xxxxxxxxxxx>
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/platform_device.h>
> +#include <linux/component.h>
> +#include <linux/of_graph.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_flip_work.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_plane_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_rect.h>
> +#include <drm/drm_fb_helper.h>
> +
> +#include "meson_drv.h"
> +#include "meson_cvbs.h"
> +#include "meson_plane.h"
> +#include "meson_crtc.h"
> +
> +#include "meson_vpp.h"
> +#include "meson_viu.h"
> +#include "meson_venc.h"
> +#include "meson_canvas.h"
> +#include "meson_registers.h"
> +
> +#define DRIVER_NAME "meson"
> +#define DRIVER_DESC "Amlogic Meson DRM driver"
> +
> +/*
> + * Video Procesing unig
> + *
> + * VPU Handles the Global Video Processing, it includes management of the
> + * clocks gates, blocks reset lines and power domains.
> + *
> + * What is missing :
> + * - Full reset of entire video processing HW blocks
> + * - Scaling and setup of the VPU clock
> + * - Bus clock gates
> + * - Powering up video processing HW blocks
> + * - Powering Up HDMI controller and PHY
> + */
> +
> +static void meson_fb_output_poll_changed(struct drm_device *dev)
> +{
> + struct meson_drm *priv = dev->dev_private;
> +
> + drm_fbdev_cma_hotplug_event(priv->fbdev);
> +}
> +
> +static const struct drm_mode_config_funcs meson_mode_config_funcs = {
> + .output_poll_changed = meson_fb_output_poll_changed,
> + .atomic_check = drm_atomic_helper_check,
> + .atomic_commit = drm_atomic_helper_commit,
> + .fb_create = drm_fb_cma_create,
> +};
> +
> +static int meson_enable_vblank(struct drm_device *dev, unsigned int crtc)
> +{
> + struct meson_drm *priv = dev->dev_private;
> +
> + meson_venc_enable_vsync(priv);
> +
> + return 0;
> +}
> +
> +static void meson_disable_vblank(struct drm_device *dev, unsigned int crtc)
> +{
> + struct meson_drm *priv = dev->dev_private;
> +
> + meson_venc_disable_vsync(priv);
> +}
> +
> +static irqreturn_t meson_irq(int irq, void *arg)
> +{
> + struct drm_device *dev = arg;
> + struct meson_drm *priv = dev->dev_private;
> +
> + (void)readl_relaxed(priv->io_base + _REG(VENC_INTFLAG));
> +
> + meson_crtc_irq(priv);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static const struct file_operations fops = {
> + .owner = THIS_MODULE,
> + .open = drm_open,
> + .release = drm_release,
> + .unlocked_ioctl = drm_ioctl,
> +#ifdef CONFIG_COMPAT
> + .compat_ioctl = drm_compat_ioctl,
> +#endif
> + .poll = drm_poll,
> + .read = drm_read,
> + .llseek = no_llseek,
> + .mmap = drm_gem_cma_mmap,
> +};
> +
> +static struct drm_driver meson_driver = {
> + .driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM |
> + DRIVER_MODESET | DRIVER_PRIME |
> + DRIVER_ATOMIC,
> +
> + /* Vblank */
> + .enable_vblank = meson_enable_vblank,
> + .disable_vblank = meson_disable_vblank,
> + .get_vblank_counter = drm_vblank_no_hw_counter,
> +
> + /* IRQ */
> + .irq_handler = meson_irq,
> +
> + /* PRIME Ops */
> + .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
> + .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
> + .gem_prime_import = drm_gem_prime_import,
> + .gem_prime_export = drm_gem_prime_export,
> + .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
> + .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
> + .gem_prime_vmap = drm_gem_cma_prime_vmap,
> + .gem_prime_vunmap = drm_gem_cma_prime_vunmap,
> + .gem_prime_mmap = drm_gem_cma_prime_mmap,
> +
> + /* GEM Ops */
> + .dumb_create = drm_gem_cma_dumb_create,
> + .dumb_destroy = drm_gem_dumb_destroy,
> + .dumb_map_offset = drm_gem_cma_dumb_map_offset,
> + .gem_free_object_unlocked = drm_gem_cma_free_object,
> + .gem_vm_ops = &drm_gem_cma_vm_ops,
> +
> + /* Misc */
> + .fops = &fops,
> + .name = DRIVER_NAME,
> + .desc = DRIVER_DESC,
> + .date = "20161109",
> + .major = 1,
> + .minor = 0,
> +};
> +
> +static struct regmap_config meson_regmap_config = {
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> + .max_register = 0x1000,
> +};
> +
> +static int meson_drv_bind(struct device *dev)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct meson_drm *priv;
> + struct drm_device *drm;
> + struct resource *res;
> + void __iomem *regs;
> + int ret;
> +
> + drm = drm_dev_alloc(&meson_driver, dev);
> + if (IS_ERR(drm))
> + return PTR_ERR(drm);
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv) {
> + ret = -ENOMEM;
> + goto free_drm;
> + }
> + drm->dev_private = priv;
> + priv->drm = drm;
> + priv->dev = dev;
> +
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "base");
> + regs = devm_ioremap_resource(dev, res);
> + if (IS_ERR(regs))
> + return PTR_ERR(regs);
> +
> + priv->io_base = regs;
> +
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hhi");
> + /* Simply ioremap since it may be a shared register zone */
> + regs = devm_ioremap(dev, res->start, resource_size(res));
> + if (!regs)
> + return -EADDRNOTAVAIL;
> +
> + priv->hhi = devm_regmap_init_mmio(dev, regs,
> + &meson_regmap_config);
> + if (IS_ERR(priv->hhi)) {
> + dev_err(&pdev->dev, "Couldn't create the HHI regmap\n");
> + return PTR_ERR(priv->hhi);
> + }
> +
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dmc");
> + /* Simply ioremap since it may be a shared register zone */
> + regs = devm_ioremap(dev, res->start, resource_size(res));
> + if (!regs)
> + return -EADDRNOTAVAIL;
> +
> + priv->dmc = devm_regmap_init_mmio(dev, regs,
> + &meson_regmap_config);
> + if (IS_ERR(priv->dmc)) {
> + dev_err(&pdev->dev, "Couldn't create the DMC regmap\n");
> + return PTR_ERR(priv->dmc);
> + }
> +
> + priv->vsync_irq = platform_get_irq(pdev, 0);
> +
> + /* Hardware Initialization */
> +
> + meson_vpp_init(priv);
> + meson_viu_init(priv);
> + meson_venc_init(priv);
> +
> + drm_vblank_init(drm, 1);
> + drm_mode_config_init(drm);
> +
> + /* Components Initialization */
> +
> + ret = component_bind_all(drm->dev, drm);
> + if (ret) {
> + dev_err(drm->dev, "Couldn't bind all components\n");
> + goto free_drm;
> + }
> +
> + ret = meson_plane_create(priv);
> + if (ret)
> + goto free_drm;
> +
> + ret = meson_crtc_create(priv);
> + if (ret)
> + goto free_drm;
> +
> + ret = drm_irq_install(drm, priv->vsync_irq);
> + if (ret)
> + goto free_drm;
> +
> + drm_mode_config_reset(drm);
> + drm->mode_config.max_width = 8192;
> + drm->mode_config.max_height = 8192;
> + drm->mode_config.funcs = &meson_mode_config_funcs;
> +
> + priv->fbdev = drm_fbdev_cma_init(drm, 32,
> + drm->mode_config.num_crtc,
> + drm->mode_config.num_connector);
> + if (IS_ERR(priv->fbdev)) {
> + ret = PTR_ERR(priv->fbdev);
> + goto free_drm;
> + }
> +
> + drm_kms_helper_poll_init(drm);
> +
> + ret = drm_dev_register(drm, 0);
> + if (ret)
> + goto free_drm;
> +
> + platform_set_drvdata(pdev, priv);

You need this before the drm_dev_register call I think.

> +
> + return 0;
> +
> +free_drm:
> + drm_dev_unref(drm);
> +
> + return ret;
> +}
> +
> +static void meson_drv_unbind(struct device *dev)
> +{
> + struct drm_device *drm = dev_get_drvdata(dev);
> + struct meson_drm *priv = drm->dev_private;
> +
> + drm_dev_unregister(drm);
> + drm_kms_helper_poll_fini(drm);
> + drm_fbdev_cma_fini(priv->fbdev);
> + drm_mode_config_cleanup(drm);
> + drm_vblank_cleanup(drm);
> + drm_dev_unref(drm);
> +}
> +
> +static const struct component_master_ops meson_drv_master_ops = {
> + .bind = meson_drv_bind,
> + .unbind = meson_drv_unbind,
> +};
> +
> +static int compare_of(struct device *dev, void *data)
> +{
> + DRM_DEBUG_DRIVER("Comparing of node %s with %s\n",
> + of_node_full_name(dev->of_node),
> + of_node_full_name(data));
> +
> + return dev->of_node == data;
> +}
> +
> +static int meson_pdev_probe(struct platform_device *pdev)
> +{
> + struct component_match *match = NULL;
> + struct device_node *np = pdev->dev.of_node;
> + struct device_node *port, *ep, *remote;
> + int count = 0;
> +
> + /* Get output port */
> + port = of_graph_get_port_by_id(np, 1);
> + if (!port) {
> + dev_err(&pdev->dev, "No output to bind\n");
> + return 0;
> + }
> +
> + /* Get each output endpoints, and connect them is available */
> + for_each_available_child_of_node(port, ep) {
> + remote = of_graph_get_remote_port_parent(ep);
> + if (!remote) {
> + dev_err(&pdev->dev, "Error retrieving the output node\n");
> + of_node_put(remote);
> + continue;
> + }
> +
> + if (!of_device_is_available(remote))
> + continue;
> +
> + component_match_add(&pdev->dev, &match, compare_of, remote);
> +
> + ++count;
> +
> + of_node_put(remote);
> + }
> +
> + /* If some endpoints were found, initialize the nodes */
> + if (count) {
> + dev_info(&pdev->dev, "Queued %d outputs on vpu\n", count);
> +
> + return component_master_add_with_match(&pdev->dev,
> + &meson_drv_master_ops,
> + match);
> + }
> +
> + /* If no output endpoints were available, simply bail out */
> + return 0;
> +};
> +
> +static const struct of_device_id dt_match[] = {
> + { .compatible = "amlogic,meson-gxbb-vpu" },
> + { .compatible = "amlogic,meson-gxl-vpu" },
> + { .compatible = "amlogic,meson-gxm-vpu" },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, dt_match);
> +
> +static struct platform_driver meson_drm_platform_driver = {
> + .probe = meson_pdev_probe,
> + .driver = {
> + .owner = THIS_MODULE,
> + .name = DRIVER_NAME,
> + .of_match_table = dt_match,
> + },
> +};
> +
> +module_platform_driver(meson_drm_platform_driver);
> +
> +MODULE_AUTHOR("Jasper St. Pierre <jstpierre@xxxxxxxxxxx>");
> +MODULE_DESCRIPTION(DRIVER_DESC);
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/meson/meson_drv.h b/drivers/gpu/drm/meson/meson_drv.h
> new file mode 100644
> index 0000000..db15eff
> --- /dev/null
> +++ b/drivers/gpu/drm/meson/meson_drv.h
> @@ -0,0 +1,68 @@
> +/*
> + * Copyright (C) 2016 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong@xxxxxxxxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
> + * 02111-1307, USA.
> + */
> +
> +#ifndef __MESON_DRV_H
> +#define __MESON_DRV_H
> +
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/of.h>
> +#include <drm/drmP.h>
> +
> +struct meson_drm {
> + struct device *dev;
> + void __iomem *io_base;
> + struct regmap *hhi;
> + struct regmap *dmc;
> + int vsync_irq;
> +
> + struct drm_device *drm;
> + struct drm_crtc *crtc;
> + struct drm_fbdev_cma *fbdev;
> + struct drm_plane *primary_plane;
> +
> + /* VPU Clocks */
> + struct clk *clk_vpu;
> + struct clk *clk_vpu0;
> + struct clk *clk_fclk_div;
> +
> + /* Components Data */
> + struct {
> + bool osd1_enabled;
> + bool osd1_interlace;
> + bool osd1_commit;
> + uint32_t osd1_ctrl_stat;
> + uint32_t osd1_blk0_cfg[5];
> + } viu;
> +
> + struct {
> + unsigned int current_mode;
> + bool cvbs_enabled;
> + } venc;
> +};
> +
> +static inline int meson_vpu_is_compatible(struct meson_drm *priv,
> + const char *compat)
> +{
> + return of_device_is_compatible(priv->dev->of_node, compat);
> +}
> +
> +
> +#endif /* __MESON_DRV_H */
> diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c
> new file mode 100644
> index 0000000..fa0178f
> --- /dev/null
> +++ b/drivers/gpu/drm/meson/meson_plane.c
> @@ -0,0 +1,150 @@
> +/*
> + * Copyright (C) 2016 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong@xxxxxxxxxxxx>
> + * Copyright (C) 2014 Endless Mobile
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
> + * 02111-1307, USA.
> + *
> + * Written by:
> + * Jasper St. Pierre <jstpierre@xxxxxxxxxxx>
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/platform_device.h>
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_plane_helper.h>
> +#include <drm/drm_rect.h>
> +
> +#include "meson_plane.h"
> +#include "meson_vpp.h"
> +#include "meson_viu.h"
> +#include "meson_canvas.h"
> +
> +struct meson_plane {
> + struct drm_plane base;
> + struct meson_drm *priv;
> +};
> +#define to_meson_plane(x) container_of(x, struct meson_plane, base)
> +
> +static int meson_plane_atomic_check(struct drm_plane *plane,
> + struct drm_plane_state *state)
> +{
> + struct drm_rect src = {
> + .x1 = state->src_x,
> + .y1 = state->src_y,
> + .x2 = state->src_x + state->src_w,
> + .y2 = state->src_y + state->src_h,
> + };
> + struct drm_rect dest = {
> + .x1 = state->crtc_x,
> + .y1 = state->crtc_y,
> + .x2 = state->crtc_x + state->crtc_w,
> + .y2 = state->crtc_y + state->crtc_h,
> + };
> +
> + if (state->fb) {
> + int ret;
> +
> + ret = drm_rect_calc_hscale(&src, &dest,
> + DRM_PLANE_HELPER_NO_SCALING,
> + DRM_PLANE_HELPER_NO_SCALING);
> + if (ret < 0)
> + return ret;
> +
> + ret = drm_rect_calc_vscale(&src, &dest,
> + DRM_PLANE_HELPER_NO_SCALING,
> + DRM_PLANE_HELPER_NO_SCALING);
> + if (ret < 0)
> + return ret;
> + }

drm_plane_helper_check_state gives you the above in less code.

> +
> + return 0;
> +}
> +
> +static void meson_plane_atomic_update(struct drm_plane *plane,
> + struct drm_plane_state *old_state)
> +{
> + struct meson_plane *meson_plane = to_meson_plane(plane);
> +
> + /*
> + * Update Coordinates
> + * Update Formats
> + * Update Buffer
> + * Enable Plane
> + */
> + meson_viu_update_osd1(meson_plane->priv, plane);
> + meson_canvas_update_osd1_buffer(meson_plane->priv, plane);
> +}
> +
> +static void meson_plane_atomic_disable(struct drm_plane *plane,
> + struct drm_plane_state *old_state)
> +{
> + struct meson_plane *meson_plane = to_meson_plane(plane);
> +
> + meson_vpp_disable_osd1(meson_plane->priv);
> +}
> +
> +static const struct drm_plane_helper_funcs meson_plane_helper_funcs = {
> + .atomic_check = meson_plane_atomic_check,
> + .atomic_disable = meson_plane_atomic_disable,
> + .atomic_update = meson_plane_atomic_update,
> +};
> +
> +static const struct drm_plane_funcs meson_plane_funcs = {
> + .update_plane = drm_atomic_helper_update_plane,
> + .disable_plane = drm_atomic_helper_disable_plane,
> + .destroy = drm_plane_cleanup,
> + .reset = drm_atomic_helper_plane_reset,
> + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
> +};
> +
> +static const uint32_t supported_drm_formats[] = {
> + DRM_FORMAT_ARGB8888,
> + DRM_FORMAT_XRGB8888,
> + DRM_FORMAT_RGB888,
> + DRM_FORMAT_RGB565,
> +};
> +
> +int meson_plane_create(struct meson_drm *priv)
> +{
> + struct meson_plane *meson_plane;
> + struct drm_plane *plane;
> +
> + meson_plane = devm_kzalloc(priv->drm->dev, sizeof(*meson_plane),
> + GFP_KERNEL);
> + if (!meson_plane)
> + return -ENOMEM;
> +
> + meson_plane->priv = priv;
> + plane = &meson_plane->base;
> +
> + drm_universal_plane_init(priv->drm, plane, 0xFF,
> + &meson_plane_funcs,
> + supported_drm_formats,
> + ARRAY_SIZE(supported_drm_formats),
> + DRM_PLANE_TYPE_PRIMARY, "meson_primary_plane");
> +
> + drm_plane_helper_add(plane, &meson_plane_helper_funcs);
> +
> + priv->primary_plane = plane;
> +
> + return 0;
> +}
> diff --git a/drivers/gpu/drm/meson/meson_plane.h b/drivers/gpu/drm/meson/meson_plane.h
> new file mode 100644
> index 0000000..babb9e1
> --- /dev/null
> +++ b/drivers/gpu/drm/meson/meson_plane.h
> @@ -0,0 +1,32 @@
> +/*
> + * Copyright (C) 2016 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong@xxxxxxxxxxxx>
> + * Copyright (C) 2014 Endless Mobile
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
> + * 02111-1307, USA.
> + *
> + * Written by:
> + * Jasper St. Pierre <jstpierre@xxxxxxxxxxx>
> + */
> +
> +#ifndef __MESON_PLANE_H
> +#define __MESON_PLANE_H
> +
> +#include "meson_drv.h"
> +
> +int meson_plane_create(struct meson_drm *priv);
> +
> +#endif /* __MESON_PLANE_H */
> diff --git a/drivers/gpu/drm/meson/meson_registers.h b/drivers/gpu/drm/meson/meson_registers.h
> new file mode 100644
> index 0000000..6adf9c1
> --- /dev/null
> +++ b/drivers/gpu/drm/meson/meson_registers.h
> @@ -0,0 +1,1395 @@
> +/*
> + * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + */
> +
> +#ifndef __MESON_REGISTERS_H
> +#define __MESON_REGISTERS_H
> +
> +/* Shift all registers by 2 */
> +#define _REG(reg) ((reg) << 2)
> +
> +#define writel_bits_relaxed(mask, val, addr) \
> + writel_relaxed((readl_relaxed(addr) & ~(mask)) | (val), addr)
> +
> +/* vpp2 */
> +#define VPP2_DUMMY_DATA 0x1900
> +#define VPP2_LINE_IN_LENGTH 0x1901
> +#define VPP2_PIC_IN_HEIGHT 0x1902
> +#define VPP2_SCALE_COEF_IDX 0x1903
> +#define VPP2_SCALE_COEF 0x1904
> +#define VPP2_VSC_REGION12_STARTP 0x1905
> +#define VPP2_VSC_REGION34_STARTP 0x1906
> +#define VPP2_VSC_REGION4_ENDP 0x1907
> +#define VPP2_VSC_START_PHASE_STEP 0x1908
> +#define VPP2_VSC_REGION0_PHASE_SLOPE 0x1909
> +#define VPP2_VSC_REGION1_PHASE_SLOPE 0x190a
> +#define VPP2_VSC_REGION3_PHASE_SLOPE 0x190b
> +#define VPP2_VSC_REGION4_PHASE_SLOPE 0x190c
> +#define VPP2_VSC_PHASE_CTRL 0x190d
> +#define VPP2_VSC_INI_PHASE 0x190e
> +#define VPP2_HSC_REGION12_STARTP 0x1910
> +#define VPP2_HSC_REGION34_STARTP 0x1911
> +#define VPP2_HSC_REGION4_ENDP 0x1912
> +#define VPP2_HSC_START_PHASE_STEP 0x1913
> +#define VPP2_HSC_REGION0_PHASE_SLOPE 0x1914
> +#define VPP2_HSC_REGION1_PHASE_SLOPE 0x1915
> +#define VPP2_HSC_REGION3_PHASE_SLOPE 0x1916
> +#define VPP2_HSC_REGION4_PHASE_SLOPE 0x1917
> +#define VPP2_HSC_PHASE_CTRL 0x1918
> +#define VPP2_SC_MISC 0x1919
> +#define VPP2_PREBLEND_VD1_H_START_END 0x191a
> +#define VPP2_PREBLEND_VD1_V_START_END 0x191b
> +#define VPP2_POSTBLEND_VD1_H_START_END 0x191c
> +#define VPP2_POSTBLEND_VD1_V_START_END 0x191d
> +#define VPP2_PREBLEND_H_SIZE 0x1920
> +#define VPP2_POSTBLEND_H_SIZE 0x1921
> +#define VPP2_HOLD_LINES 0x1922
> +#define VPP2_BLEND_ONECOLOR_CTRL 0x1923
> +#define VPP2_PREBLEND_CURRENT_XY 0x1924
> +#define VPP2_POSTBLEND_CURRENT_XY 0x1925
> +#define VPP2_MISC 0x1926
> +#define VPP2_OFIFO_SIZE 0x1927
> +#define VPP2_FIFO_STATUS 0x1928
> +#define VPP2_SMOKE_CTRL 0x1929
> +#define VPP2_SMOKE1_VAL 0x192a
> +#define VPP2_SMOKE2_VAL 0x192b
> +#define VPP2_SMOKE1_H_START_END 0x192d
> +#define VPP2_SMOKE1_V_START_END 0x192e
> +#define VPP2_SMOKE2_H_START_END 0x192f
> +#define VPP2_SMOKE2_V_START_END 0x1930
> +#define VPP2_SCO_FIFO_CTRL 0x1933
> +#define VPP2_HSC_PHASE_CTRL1 0x1934
> +#define VPP2_HSC_INI_PAT_CTRL 0x1935
> +#define VPP2_VADJ_CTRL 0x1940
> +#define VPP2_VADJ1_Y 0x1941
> +#define VPP2_VADJ1_MA_MB 0x1942
> +#define VPP2_VADJ1_MC_MD 0x1943
> +#define VPP2_VADJ2_Y 0x1944
> +#define VPP2_VADJ2_MA_MB 0x1945
> +#define VPP2_VADJ2_MC_MD 0x1946
> +#define VPP2_MATRIX_PROBE_COLOR 0x195c
> +#define VPP2_MATRIX_HL_COLOR 0x195d
> +#define VPP2_MATRIX_PROBE_POS 0x195e
> +#define VPP2_MATRIX_CTRL 0x195f
> +#define VPP2_MATRIX_COEF00_01 0x1960
> +#define VPP2_MATRIX_COEF02_10 0x1961
> +#define VPP2_MATRIX_COEF11_12 0x1962
> +#define VPP2_MATRIX_COEF20_21 0x1963
> +#define VPP2_MATRIX_COEF22 0x1964
> +#define VPP2_MATRIX_OFFSET0_1 0x1965
> +#define VPP2_MATRIX_OFFSET2 0x1966
> +#define VPP2_MATRIX_PRE_OFFSET0_1 0x1967
> +#define VPP2_MATRIX_PRE_OFFSET2 0x1968
> +#define VPP2_DUMMY_DATA1 0x1969
> +#define VPP2_GAINOFF_CTRL0 0x196a
> +#define VPP2_GAINOFF_CTRL1 0x196b
> +#define VPP2_GAINOFF_CTRL2 0x196c
> +#define VPP2_GAINOFF_CTRL3 0x196d
> +#define VPP2_GAINOFF_CTRL4 0x196e
> +#define VPP2_CHROMA_ADDR_PORT 0x1970
> +#define VPP2_CHROMA_DATA_PORT 0x1971
> +#define VPP2_GCLK_CTRL0 0x1972
> +#define VPP2_GCLK_CTRL1 0x1973
> +#define VPP2_SC_GCLK_CTRL 0x1974
> +#define VPP2_MISC1 0x1976
> +#define VPP2_DNLP_CTRL_00 0x1981
> +#define VPP2_DNLP_CTRL_01 0x1982
> +#define VPP2_DNLP_CTRL_02 0x1983
> +#define VPP2_DNLP_CTRL_03 0x1984
> +#define VPP2_DNLP_CTRL_04 0x1985
> +#define VPP2_DNLP_CTRL_05 0x1986
> +#define VPP2_DNLP_CTRL_06 0x1987
> +#define VPP2_DNLP_CTRL_07 0x1988
> +#define VPP2_DNLP_CTRL_08 0x1989
> +#define VPP2_DNLP_CTRL_09 0x198a
> +#define VPP2_DNLP_CTRL_10 0x198b
> +#define VPP2_DNLP_CTRL_11 0x198c
> +#define VPP2_DNLP_CTRL_12 0x198d
> +#define VPP2_DNLP_CTRL_13 0x198e
> +#define VPP2_DNLP_CTRL_14 0x198f
> +#define VPP2_DNLP_CTRL_15 0x1990
> +#define VPP2_VE_ENABLE_CTRL 0x19a1
> +#define VPP2_VE_DEMO_LEFT_TOP_SCREEN_WIDTH 0x19a2
> +#define VPP2_VE_DEMO_CENTER_BAR 0x19a3
> +#define VPP2_VE_H_V_SIZE 0x19a4
> +#define VPP2_VDO_MEAS_CTRL 0x19a8
> +#define VPP2_VDO_MEAS_VS_COUNT_HI 0x19a9
> +#define VPP2_VDO_MEAS_VS_COUNT_LO 0x19aa
> +#define VPP2_OSD_VSC_PHASE_STEP 0x19c0
> +#define VPP2_OSD_VSC_INI_PHASE 0x19c1
> +#define VPP2_OSD_VSC_CTRL0 0x19c2
> +#define VPP2_OSD_HSC_PHASE_STEP 0x19c3
> +#define VPP2_OSD_HSC_INI_PHASE 0x19c4
> +#define VPP2_OSD_HSC_CTRL0 0x19c5
> +#define VPP2_OSD_HSC_INI_PAT_CTRL 0x19c6
> +#define VPP2_OSD_SC_DUMMY_DATA 0x19c7
> +#define VPP2_OSD_SC_CTRL0 0x19c8
> +#define VPP2_OSD_SCI_WH_M1 0x19c9
> +#define VPP2_OSD_SCO_H_START_END 0x19ca
> +#define VPP2_OSD_SCO_V_START_END 0x19cb
> +#define VPP2_OSD_SCALE_COEF_IDX 0x19cc
> +#define VPP2_OSD_SCALE_COEF 0x19cd
> +#define VPP2_INT_LINE_NUM 0x19ce
> +
> +/* viu */
> +#define VIU_ADDR_START 0x1a00
> +#define VIU_ADDR_END 0x1aff
> +#define VIU_SW_RESET 0x1a01
> +#define VIU_MISC_CTRL0 0x1a06
> +#define VIU_MISC_CTRL1 0x1a07
> +#define D2D3_INTF_LENGTH 0x1a08
> +#define D2D3_INTF_CTRL0 0x1a09
> +#define VIU_OSD1_CTRL_STAT 0x1a10
> +#define VIU_OSD1_CTRL_STAT2 0x1a2d
> +#define VIU_OSD1_COLOR_ADDR 0x1a11
> +#define VIU_OSD1_COLOR 0x1a12
> +#define VIU_OSD1_TCOLOR_AG0 0x1a17
> +#define VIU_OSD1_TCOLOR_AG1 0x1a18
> +#define VIU_OSD1_TCOLOR_AG2 0x1a19
> +#define VIU_OSD1_TCOLOR_AG3 0x1a1a
> +#define VIU_OSD1_BLK0_CFG_W0 0x1a1b
> +#define VIU_OSD1_BLK1_CFG_W0 0x1a1f
> +#define VIU_OSD1_BLK2_CFG_W0 0x1a23
> +#define VIU_OSD1_BLK3_CFG_W0 0x1a27
> +#define VIU_OSD1_BLK0_CFG_W1 0x1a1c
> +#define VIU_OSD1_BLK1_CFG_W1 0x1a20
> +#define VIU_OSD1_BLK2_CFG_W1 0x1a24
> +#define VIU_OSD1_BLK3_CFG_W1 0x1a28
> +#define VIU_OSD1_BLK0_CFG_W2 0x1a1d
> +#define VIU_OSD1_BLK1_CFG_W2 0x1a21
> +#define VIU_OSD1_BLK2_CFG_W2 0x1a25
> +#define VIU_OSD1_BLK3_CFG_W2 0x1a29
> +#define VIU_OSD1_BLK0_CFG_W3 0x1a1e
> +#define VIU_OSD1_BLK1_CFG_W3 0x1a22
> +#define VIU_OSD1_BLK2_CFG_W3 0x1a26
> +#define VIU_OSD1_BLK3_CFG_W3 0x1a2a
> +#define VIU_OSD1_BLK0_CFG_W4 0x1a13
> +#define VIU_OSD1_BLK1_CFG_W4 0x1a14
> +#define VIU_OSD1_BLK2_CFG_W4 0x1a15
> +#define VIU_OSD1_BLK3_CFG_W4 0x1a16
> +#define VIU_OSD1_FIFO_CTRL_STAT 0x1a2b
> +#define VIU_OSD1_TEST_RDDATA 0x1a2c
> +#define VIU_OSD1_PROT_CTRL 0x1a2e
> +#define VIU_OSD2_CTRL_STAT 0x1a30
> +#define VIU_OSD2_CTRL_STAT2 0x1a4d
> +#define VIU_OSD2_COLOR_ADDR 0x1a31
> +#define VIU_OSD2_COLOR 0x1a32
> +#define VIU_OSD2_HL1_H_START_END 0x1a33
> +#define VIU_OSD2_HL1_V_START_END 0x1a34
> +#define VIU_OSD2_HL2_H_START_END 0x1a35
> +#define VIU_OSD2_HL2_V_START_END 0x1a36
> +#define VIU_OSD2_TCOLOR_AG0 0x1a37
> +#define VIU_OSD2_TCOLOR_AG1 0x1a38
> +#define VIU_OSD2_TCOLOR_AG2 0x1a39
> +#define VIU_OSD2_TCOLOR_AG3 0x1a3a
> +#define VIU_OSD2_BLK0_CFG_W0 0x1a3b
> +#define VIU_OSD2_BLK1_CFG_W0 0x1a3f
> +#define VIU_OSD2_BLK2_CFG_W0 0x1a43
> +#define VIU_OSD2_BLK3_CFG_W0 0x1a47
> +#define VIU_OSD2_BLK0_CFG_W1 0x1a3c
> +#define VIU_OSD2_BLK1_CFG_W1 0x1a40
> +#define VIU_OSD2_BLK2_CFG_W1 0x1a44
> +#define VIU_OSD2_BLK3_CFG_W1 0x1a48
> +#define VIU_OSD2_BLK0_CFG_W2 0x1a3d
> +#define VIU_OSD2_BLK1_CFG_W2 0x1a41
> +#define VIU_OSD2_BLK2_CFG_W2 0x1a45
> +#define VIU_OSD2_BLK3_CFG_W2 0x1a49
> +#define VIU_OSD2_BLK0_CFG_W3 0x1a3e
> +#define VIU_OSD2_BLK1_CFG_W3 0x1a42
> +#define VIU_OSD2_BLK2_CFG_W3 0x1a46
> +#define VIU_OSD2_BLK3_CFG_W3 0x1a4a
> +#define VIU_OSD2_BLK0_CFG_W4 0x1a64
> +#define VIU_OSD2_BLK1_CFG_W4 0x1a65
> +#define VIU_OSD2_BLK2_CFG_W4 0x1a66
> +#define VIU_OSD2_BLK3_CFG_W4 0x1a67
> +#define VIU_OSD2_FIFO_CTRL_STAT 0x1a4b
> +#define VIU_OSD2_TEST_RDDATA 0x1a4c
> +#define VIU_OSD2_PROT_CTRL 0x1a4e
> +
> +#define VD1_IF0_GEN_REG 0x1a50
> +#define VD1_IF0_CANVAS0 0x1a51
> +#define VD1_IF0_CANVAS1 0x1a52
> +#define VD1_IF0_LUMA_X0 0x1a53
> +#define VD1_IF0_LUMA_Y0 0x1a54
> +#define VD1_IF0_CHROMA_X0 0x1a55
> +#define VD1_IF0_CHROMA_Y0 0x1a56
> +#define VD1_IF0_LUMA_X1 0x1a57
> +#define VD1_IF0_LUMA_Y1 0x1a58
> +#define VD1_IF0_CHROMA_X1 0x1a59
> +#define VD1_IF0_CHROMA_Y1 0x1a5a
> +#define VD1_IF0_RPT_LOOP 0x1a5b
> +#define VD1_IF0_LUMA0_RPT_PAT 0x1a5c
> +#define VD1_IF0_CHROMA0_RPT_PAT 0x1a5d
> +#define VD1_IF0_LUMA1_RPT_PAT 0x1a5e
> +#define VD1_IF0_CHROMA1_RPT_PAT 0x1a5f
> +#define VD1_IF0_LUMA_PSEL 0x1a60
> +#define VD1_IF0_CHROMA_PSEL 0x1a61
> +#define VD1_IF0_DUMMY_PIXEL 0x1a62
> +#define VD1_IF0_LUMA_FIFO_SIZE 0x1a63
> +#define VD1_IF0_RANGE_MAP_Y 0x1a6a
> +#define VD1_IF0_RANGE_MAP_CB 0x1a6b
> +#define VD1_IF0_RANGE_MAP_CR 0x1a6c
> +#define VD1_IF0_GEN_REG2 0x1a6d
> +#define VD1_IF0_PROT_CNTL 0x1a6e
> +#define VIU_VD1_FMT_CTRL 0x1a68
> +#define VIU_VD1_FMT_W 0x1a69
> +#define VD2_IF0_GEN_REG 0x1a70
> +#define VD2_IF0_CANVAS0 0x1a71
> +#define VD2_IF0_CANVAS1 0x1a72
> +#define VD2_IF0_LUMA_X0 0x1a73
> +#define VD2_IF0_LUMA_Y0 0x1a74
> +#define VD2_IF0_CHROMA_X0 0x1a75
> +#define VD2_IF0_CHROMA_Y0 0x1a76
> +#define VD2_IF0_LUMA_X1 0x1a77
> +#define VD2_IF0_LUMA_Y1 0x1a78
> +#define VD2_IF0_CHROMA_X1 0x1a79
> +#define VD2_IF0_CHROMA_Y1 0x1a7a
> +#define VD2_IF0_RPT_LOOP 0x1a7b
> +#define VD2_IF0_LUMA0_RPT_PAT 0x1a7c
> +#define VD2_IF0_CHROMA0_RPT_PAT 0x1a7d
> +#define VD2_IF0_LUMA1_RPT_PAT 0x1a7e
> +#define VD2_IF0_CHROMA1_RPT_PAT 0x1a7f
> +#define VD2_IF0_LUMA_PSEL 0x1a80
> +#define VD2_IF0_CHROMA_PSEL 0x1a81
> +#define VD2_IF0_DUMMY_PIXEL 0x1a82
> +#define VD2_IF0_LUMA_FIFO_SIZE 0x1a83
> +#define VD2_IF0_RANGE_MAP_Y 0x1a8a
> +#define VD2_IF0_RANGE_MAP_CB 0x1a8b
> +#define VD2_IF0_RANGE_MAP_CR 0x1a8c
> +#define VD2_IF0_GEN_REG2 0x1a8d
> +#define VD2_IF0_PROT_CNTL 0x1a8e
> +#define VIU_VD2_FMT_CTRL 0x1a88
> +#define VIU_VD2_FMT_W 0x1a89
> +
> +/* VIU Matrix Registers */
> +#define VIU_OSD1_MATRIX_CTRL 0x1a90
> +#define VIU_OSD1_MATRIX_COEF00_01 0x1a91
> +#define VIU_OSD1_MATRIX_COEF02_10 0x1a92
> +#define VIU_OSD1_MATRIX_COEF11_12 0x1a93
> +#define VIU_OSD1_MATRIX_COEF20_21 0x1a94
> +#define VIU_OSD1_MATRIX_COLMOD_COEF42 0x1a95
> +#define VIU_OSD1_MATRIX_OFFSET0_1 0x1a96
> +#define VIU_OSD1_MATRIX_OFFSET2 0x1a97
> +#define VIU_OSD1_MATRIX_PRE_OFFSET0_1 0x1a98
> +#define VIU_OSD1_MATRIX_PRE_OFFSET2 0x1a99
> +#define VIU_OSD1_MATRIX_COEF22_30 0x1a9d
> +#define VIU_OSD1_MATRIX_COEF31_32 0x1a9e
> +#define VIU_OSD1_MATRIX_COEF40_41 0x1a9f
> +#define VIU_OSD1_EOTF_CTL 0x1ad4
> +#define VIU_OSD1_EOTF_COEF00_01 0x1ad5
> +#define VIU_OSD1_EOTF_COEF02_10 0x1ad6
> +#define VIU_OSD1_EOTF_COEF11_12 0x1ad7
> +#define VIU_OSD1_EOTF_COEF20_21 0x1ad8
> +#define VIU_OSD1_EOTF_COEF22_RS 0x1ad9
> +#define VIU_OSD1_EOTF_LUT_ADDR_PORT 0x1ada
> +#define VIU_OSD1_EOTF_LUT_DATA_PORT 0x1adb
> +#define VIU_OSD1_OETF_CTL 0x1adc
> +#define VIU_OSD1_OETF_LUT_ADDR_PORT 0x1add
> +#define VIU_OSD1_OETF_LUT_DATA_PORT 0x1ade
> +
> +/* vpp */
> +#define VPP_DUMMY_DATA 0x1d00
> +#define VPP_LINE_IN_LENGTH 0x1d01
> +#define VPP_PIC_IN_HEIGHT 0x1d02
> +#define VPP_SCALE_COEF_IDX 0x1d03
> +#define VPP_SCALE_COEF 0x1d04
> +#define VPP_VSC_REGION12_STARTP 0x1d05
> +#define VPP_VSC_REGION34_STARTP 0x1d06
> +#define VPP_VSC_REGION4_ENDP 0x1d07
> +#define VPP_VSC_START_PHASE_STEP 0x1d08
> +#define VPP_VSC_REGION0_PHASE_SLOPE 0x1d09
> +#define VPP_VSC_REGION1_PHASE_SLOPE 0x1d0a
> +#define VPP_VSC_REGION3_PHASE_SLOPE 0x1d0b
> +#define VPP_VSC_REGION4_PHASE_SLOPE 0x1d0c
> +#define VPP_VSC_PHASE_CTRL 0x1d0d
> +#define VPP_VSC_INI_PHASE 0x1d0e
> +#define VPP_HSC_REGION12_STARTP 0x1d10
> +#define VPP_HSC_REGION34_STARTP 0x1d11
> +#define VPP_HSC_REGION4_ENDP 0x1d12
> +#define VPP_HSC_START_PHASE_STEP 0x1d13
> +#define VPP_HSC_REGION0_PHASE_SLOPE 0x1d14
> +#define VPP_HSC_REGION1_PHASE_SLOPE 0x1d15
> +#define VPP_HSC_REGION3_PHASE_SLOPE 0x1d16
> +#define VPP_HSC_REGION4_PHASE_SLOPE 0x1d17
> +#define VPP_HSC_PHASE_CTRL 0x1d18
> +#define VPP_SC_MISC 0x1d19
> +#define VPP_PREBLEND_VD1_H_START_END 0x1d1a
> +#define VPP_PREBLEND_VD1_V_START_END 0x1d1b
> +#define VPP_POSTBLEND_VD1_H_START_END 0x1d1c
> +#define VPP_POSTBLEND_VD1_V_START_END 0x1d1d
> +#define VPP_BLEND_VD2_H_START_END 0x1d1e
> +#define VPP_BLEND_VD2_V_START_END 0x1d1f
> +#define VPP_PREBLEND_H_SIZE 0x1d20
> +#define VPP_POSTBLEND_H_SIZE 0x1d21
> +#define VPP_HOLD_LINES 0x1d22
> +#define VPP_BLEND_ONECOLOR_CTRL 0x1d23
> +#define VPP_PREBLEND_CURRENT_XY 0x1d24
> +#define VPP_POSTBLEND_CURRENT_XY 0x1d25
> +#define VPP_MISC 0x1d26
> +#define VPP_PREBLEND_ENABLE BIT(6)
> +#define VPP_POSTBLEND_ENABLE BIT(7)
> +#define VPP_OSD2_ALPHA_PREMULT BIT(8)
> +#define VPP_OSD1_ALPHA_PREMULT BIT(9)
> +#define VPP_VD1_POSTBLEND BIT(10)
> +#define VPP_VD2_POSTBLEND BIT(11)
> +#define VPP_OSD1_POSTBLEND BIT(12)
> +#define VPP_OSD2_POSTBLEND BIT(13)
> +#define VPP_VD1_PREBLEND BIT(14)
> +#define VPP_VD2_PREBLEND BIT(15)
> +#define VPP_OSD1_PREBLEND BIT(16)
> +#define VPP_OSD2_PREBLEND BIT(17)
> +#define VPP_OFIFO_SIZE 0x1d27
> +#define VPP_FIFO_STATUS 0x1d28
> +#define VPP_SMOKE_CTRL 0x1d29
> +#define VPP_SMOKE1_VAL 0x1d2a
> +#define VPP_SMOKE2_VAL 0x1d2b
> +#define VPP_SMOKE3_VAL 0x1d2c
> +#define VPP_SMOKE1_H_START_END 0x1d2d
> +#define VPP_SMOKE1_V_START_END 0x1d2e
> +#define VPP_SMOKE2_H_START_END 0x1d2f
> +#define VPP_SMOKE2_V_START_END 0x1d30
> +#define VPP_SMOKE3_H_START_END 0x1d31
> +#define VPP_SMOKE3_V_START_END 0x1d32
> +#define VPP_SCO_FIFO_CTRL 0x1d33
> +#define VPP_HSC_PHASE_CTRL1 0x1d34
> +#define VPP_HSC_INI_PAT_CTRL 0x1d35
> +#define VPP_VADJ_CTRL 0x1d40
> +#define VPP_VADJ1_Y 0x1d41
> +#define VPP_VADJ1_MA_MB 0x1d42
> +#define VPP_VADJ1_MC_MD 0x1d43
> +#define VPP_VADJ2_Y 0x1d44
> +#define VPP_VADJ2_MA_MB 0x1d45
> +#define VPP_VADJ2_MC_MD 0x1d46
> +#define VPP_HSHARP_CTRL 0x1d50
> +#define VPP_HSHARP_LUMA_THRESH01 0x1d51
> +#define VPP_HSHARP_LUMA_THRESH23 0x1d52
> +#define VPP_HSHARP_CHROMA_THRESH01 0x1d53
> +#define VPP_HSHARP_CHROMA_THRESH23 0x1d54
> +#define VPP_HSHARP_LUMA_GAIN 0x1d55
> +#define VPP_HSHARP_CHROMA_GAIN 0x1d56
> +#define VPP_MATRIX_PROBE_COLOR 0x1d5c
> +#define VPP_MATRIX_HL_COLOR 0x1d5d
> +#define VPP_MATRIX_PROBE_POS 0x1d5e
> +#define VPP_MATRIX_CTRL 0x1d5f
> +#define VPP_MATRIX_COEF00_01 0x1d60
> +#define VPP_MATRIX_COEF02_10 0x1d61
> +#define VPP_MATRIX_COEF11_12 0x1d62
> +#define VPP_MATRIX_COEF20_21 0x1d63
> +#define VPP_MATRIX_COEF22 0x1d64
> +#define VPP_MATRIX_OFFSET0_1 0x1d65
> +#define VPP_MATRIX_OFFSET2 0x1d66
> +#define VPP_MATRIX_PRE_OFFSET0_1 0x1d67
> +#define VPP_MATRIX_PRE_OFFSET2 0x1d68
> +#define VPP_DUMMY_DATA1 0x1d69
> +#define VPP_GAINOFF_CTRL0 0x1d6a
> +#define VPP_GAINOFF_CTRL1 0x1d6b
> +#define VPP_GAINOFF_CTRL2 0x1d6c
> +#define VPP_GAINOFF_CTRL3 0x1d6d
> +#define VPP_GAINOFF_CTRL4 0x1d6e
> +#define VPP_CHROMA_ADDR_PORT 0x1d70
> +#define VPP_CHROMA_DATA_PORT 0x1d71
> +#define VPP_GCLK_CTRL0 0x1d72
> +#define VPP_GCLK_CTRL1 0x1d73
> +#define VPP_SC_GCLK_CTRL 0x1d74
> +#define VPP_MISC1 0x1d76
> +#define VPP_BLACKEXT_CTRL 0x1d80
> +#define VPP_DNLP_CTRL_00 0x1d81
> +#define VPP_DNLP_CTRL_01 0x1d82
> +#define VPP_DNLP_CTRL_02 0x1d83
> +#define VPP_DNLP_CTRL_03 0x1d84
> +#define VPP_DNLP_CTRL_04 0x1d85
> +#define VPP_DNLP_CTRL_05 0x1d86
> +#define VPP_DNLP_CTRL_06 0x1d87
> +#define VPP_DNLP_CTRL_07 0x1d88
> +#define VPP_DNLP_CTRL_08 0x1d89
> +#define VPP_DNLP_CTRL_09 0x1d8a
> +#define VPP_DNLP_CTRL_10 0x1d8b
> +#define VPP_DNLP_CTRL_11 0x1d8c
> +#define VPP_DNLP_CTRL_12 0x1d8d
> +#define VPP_DNLP_CTRL_13 0x1d8e
> +#define VPP_DNLP_CTRL_14 0x1d8f
> +#define VPP_DNLP_CTRL_15 0x1d90
> +#define VPP_PEAKING_HGAIN 0x1d91
> +#define VPP_PEAKING_VGAIN 0x1d92
> +#define VPP_PEAKING_NLP_1 0x1d93
> +#define VPP_DOLBY_CTRL 0x1d93
> +#define VPP_PEAKING_NLP_2 0x1d94
> +#define VPP_PEAKING_NLP_3 0x1d95
> +#define VPP_PEAKING_NLP_4 0x1d96
> +#define VPP_PEAKING_NLP_5 0x1d97
> +#define VPP_SHARP_LIMIT 0x1d98
> +#define VPP_VLTI_CTRL 0x1d99
> +#define VPP_HLTI_CTRL 0x1d9a
> +#define VPP_CTI_CTRL 0x1d9b
> +#define VPP_BLUE_STRETCH_1 0x1d9c
> +#define VPP_BLUE_STRETCH_2 0x1d9d
> +#define VPP_BLUE_STRETCH_3 0x1d9e
> +#define VPP_CCORING_CTRL 0x1da0
> +#define VPP_VE_ENABLE_CTRL 0x1da1
> +#define VPP_VE_DEMO_LEFT_TOP_SCREEN_WIDTH 0x1da2
> +#define VPP_VE_DEMO_CENTER_BAR 0x1da3
> +#define VPP_VE_H_V_SIZE 0x1da4
> +#define VPP_VDO_MEAS_CTRL 0x1da8
> +#define VPP_VDO_MEAS_VS_COUNT_HI 0x1da9
> +#define VPP_VDO_MEAS_VS_COUNT_LO 0x1daa
> +#define VPP_INPUT_CTRL 0x1dab
> +#define VPP_CTI_CTRL2 0x1dac
> +#define VPP_PEAKING_SAT_THD1 0x1dad
> +#define VPP_PEAKING_SAT_THD2 0x1dae
> +#define VPP_PEAKING_SAT_THD3 0x1daf
> +#define VPP_PEAKING_SAT_THD4 0x1db0
> +#define VPP_PEAKING_SAT_THD5 0x1db1
> +#define VPP_PEAKING_SAT_THD6 0x1db2
> +#define VPP_PEAKING_SAT_THD7 0x1db3
> +#define VPP_PEAKING_SAT_THD8 0x1db4
> +#define VPP_PEAKING_SAT_THD9 0x1db5
> +#define VPP_PEAKING_GAIN_ADD1 0x1db6
> +#define VPP_PEAKING_GAIN_ADD2 0x1db7
> +#define VPP_PEAKING_DNLP 0x1db8
> +#define VPP_SHARP_DEMO_WIN_CTRL1 0x1db9
> +#define VPP_SHARP_DEMO_WIN_CTRL2 0x1dba
> +#define VPP_FRONT_HLTI_CTRL 0x1dbb
> +#define VPP_FRONT_CTI_CTRL 0x1dbc
> +#define VPP_FRONT_CTI_CTRL2 0x1dbd
> +#define VPP_OSD_VSC_PHASE_STEP 0x1dc0
> +#define VPP_OSD_VSC_INI_PHASE 0x1dc1
> +#define VPP_OSD_VSC_CTRL0 0x1dc2
> +#define VPP_OSD_HSC_PHASE_STEP 0x1dc3
> +#define VPP_OSD_HSC_INI_PHASE 0x1dc4
> +#define VPP_OSD_HSC_CTRL0 0x1dc5
> +#define VPP_OSD_HSC_INI_PAT_CTRL 0x1dc6
> +#define VPP_OSD_SC_DUMMY_DATA 0x1dc7
> +#define VPP_OSD_SC_CTRL0 0x1dc8
> +#define VPP_OSD_SCI_WH_M1 0x1dc9
> +#define VPP_OSD_SCO_H_START_END 0x1dca
> +#define VPP_OSD_SCO_V_START_END 0x1dcb
> +#define VPP_OSD_SCALE_COEF_IDX 0x1dcc
> +#define VPP_OSD_SCALE_COEF 0x1dcd
> +#define VPP_INT_LINE_NUM 0x1dce
> +
> +/* viu2 */
> +#define VIU2_ADDR_START 0x1e00
> +#define VIU2_ADDR_END 0x1eff
> +#define VIU2_SW_RESET 0x1e01
> +#define VIU2_OSD1_CTRL_STAT 0x1e10
> +#define VIU2_OSD1_CTRL_STAT2 0x1e2d
> +#define VIU2_OSD1_COLOR_ADDR 0x1e11
> +#define VIU2_OSD1_COLOR 0x1e12
> +#define VIU2_OSD1_TCOLOR_AG0 0x1e17
> +#define VIU2_OSD1_TCOLOR_AG1 0x1e18
> +#define VIU2_OSD1_TCOLOR_AG2 0x1e19
> +#define VIU2_OSD1_TCOLOR_AG3 0x1e1a
> +#define VIU2_OSD1_BLK0_CFG_W0 0x1e1b
> +#define VIU2_OSD1_BLK1_CFG_W0 0x1e1f
> +#define VIU2_OSD1_BLK2_CFG_W0 0x1e23
> +#define VIU2_OSD1_BLK3_CFG_W0 0x1e27
> +#define VIU2_OSD1_BLK0_CFG_W1 0x1e1c
> +#define VIU2_OSD1_BLK1_CFG_W1 0x1e20
> +#define VIU2_OSD1_BLK2_CFG_W1 0x1e24
> +#define VIU2_OSD1_BLK3_CFG_W1 0x1e28
> +#define VIU2_OSD1_BLK0_CFG_W2 0x1e1d
> +#define VIU2_OSD1_BLK1_CFG_W2 0x1e21
> +#define VIU2_OSD1_BLK2_CFG_W2 0x1e25
> +#define VIU2_OSD1_BLK3_CFG_W2 0x1e29
> +#define VIU2_OSD1_BLK0_CFG_W3 0x1e1e
> +#define VIU2_OSD1_BLK1_CFG_W3 0x1e22
> +#define VIU2_OSD1_BLK2_CFG_W3 0x1e26
> +#define VIU2_OSD1_BLK3_CFG_W3 0x1e2a
> +#define VIU2_OSD1_BLK0_CFG_W4 0x1e13
> +#define VIU2_OSD1_BLK1_CFG_W4 0x1e14
> +#define VIU2_OSD1_BLK2_CFG_W4 0x1e15
> +#define VIU2_OSD1_BLK3_CFG_W4 0x1e16
> +#define VIU2_OSD1_FIFO_CTRL_STAT 0x1e2b
> +#define VIU2_OSD1_TEST_RDDATA 0x1e2c
> +#define VIU2_OSD1_PROT_CTRL 0x1e2e
> +#define VIU2_OSD2_CTRL_STAT 0x1e30
> +#define VIU2_OSD2_CTRL_STAT2 0x1e4d
> +#define VIU2_OSD2_COLOR_ADDR 0x1e31
> +#define VIU2_OSD2_COLOR 0x1e32
> +#define VIU2_OSD2_HL1_H_START_END 0x1e33
> +#define VIU2_OSD2_HL1_V_START_END 0x1e34
> +#define VIU2_OSD2_HL2_H_START_END 0x1e35
> +#define VIU2_OSD2_HL2_V_START_END 0x1e36
> +#define VIU2_OSD2_TCOLOR_AG0 0x1e37
> +#define VIU2_OSD2_TCOLOR_AG1 0x1e38
> +#define VIU2_OSD2_TCOLOR_AG2 0x1e39
> +#define VIU2_OSD2_TCOLOR_AG3 0x1e3a
> +#define VIU2_OSD2_BLK0_CFG_W0 0x1e3b
> +#define VIU2_OSD2_BLK1_CFG_W0 0x1e3f
> +#define VIU2_OSD2_BLK2_CFG_W0 0x1e43
> +#define VIU2_OSD2_BLK3_CFG_W0 0x1e47
> +#define VIU2_OSD2_BLK0_CFG_W1 0x1e3c
> +#define VIU2_OSD2_BLK1_CFG_W1 0x1e40
> +#define VIU2_OSD2_BLK2_CFG_W1 0x1e44
> +#define VIU2_OSD2_BLK3_CFG_W1 0x1e48
> +#define VIU2_OSD2_BLK0_CFG_W2 0x1e3d
> +#define VIU2_OSD2_BLK1_CFG_W2 0x1e41
> +#define VIU2_OSD2_BLK2_CFG_W2 0x1e45
> +#define VIU2_OSD2_BLK3_CFG_W2 0x1e49
> +#define VIU2_OSD2_BLK0_CFG_W3 0x1e3e
> +#define VIU2_OSD2_BLK1_CFG_W3 0x1e42
> +#define VIU2_OSD2_BLK2_CFG_W3 0x1e46
> +#define VIU2_OSD2_BLK3_CFG_W3 0x1e4a
> +#define VIU2_OSD2_BLK0_CFG_W4 0x1e64
> +#define VIU2_OSD2_BLK1_CFG_W4 0x1e65
> +#define VIU2_OSD2_BLK2_CFG_W4 0x1e66
> +#define VIU2_OSD2_BLK3_CFG_W4 0x1e67
> +#define VIU2_OSD2_FIFO_CTRL_STAT 0x1e4b
> +#define VIU2_OSD2_TEST_RDDATA 0x1e4c
> +#define VIU2_OSD2_PROT_CTRL 0x1e4e
> +#define VIU2_VD1_IF0_GEN_REG 0x1e50
> +#define VIU2_VD1_IF0_CANVAS0 0x1e51
> +#define VIU2_VD1_IF0_CANVAS1 0x1e52
> +#define VIU2_VD1_IF0_LUMA_X0 0x1e53
> +#define VIU2_VD1_IF0_LUMA_Y0 0x1e54
> +#define VIU2_VD1_IF0_CHROMA_X0 0x1e55
> +#define VIU2_VD1_IF0_CHROMA_Y0 0x1e56
> +#define VIU2_VD1_IF0_LUMA_X1 0x1e57
> +#define VIU2_VD1_IF0_LUMA_Y1 0x1e58
> +#define VIU2_VD1_IF0_CHROMA_X1 0x1e59
> +#define VIU2_VD1_IF0_CHROMA_Y1 0x1e5a
> +#define VIU2_VD1_IF0_RPT_LOOP 0x1e5b
> +#define VIU2_VD1_IF0_LUMA0_RPT_PAT 0x1e5c
> +#define VIU2_VD1_IF0_CHROMA0_RPT_PAT 0x1e5d
> +#define VIU2_VD1_IF0_LUMA1_RPT_PAT 0x1e5e
> +#define VIU2_VD1_IF0_CHROMA1_RPT_PAT 0x1e5f
> +#define VIU2_VD1_IF0_LUMA_PSEL 0x1e60
> +#define VIU2_VD1_IF0_CHROMA_PSEL 0x1e61
> +#define VIU2_VD1_IF0_DUMMY_PIXEL 0x1e62
> +#define VIU2_VD1_IF0_LUMA_FIFO_SIZE 0x1e63
> +#define VIU2_VD1_IF0_RANGE_MAP_Y 0x1e6a
> +#define VIU2_VD1_IF0_RANGE_MAP_CB 0x1e6b
> +#define VIU2_VD1_IF0_RANGE_MAP_CR 0x1e6c
> +#define VIU2_VD1_IF0_GEN_REG2 0x1e6d
> +#define VIU2_VD1_IF0_PROT_CNTL 0x1e6e
> +#define VIU2_VD1_FMT_CTRL 0x1e68
> +#define VIU2_VD1_FMT_W 0x1e69
> +
> +/* encode */
> +#define ENCP_VFIFO2VD_CTL 0x1b58
> +#define ENCP_VFIFO2VD_PIXEL_START 0x1b59
> +#define ENCP_VFIFO2VD_PIXEL_END 0x1b5a
> +#define ENCP_VFIFO2VD_LINE_TOP_START 0x1b5b
> +#define ENCP_VFIFO2VD_LINE_TOP_END 0x1b5c
> +#define ENCP_VFIFO2VD_LINE_BOT_START 0x1b5d
> +#define ENCP_VFIFO2VD_LINE_BOT_END 0x1b5e
> +#define VENC_SYNC_ROUTE 0x1b60
> +#define VENC_VIDEO_EXSRC 0x1b61
> +#define VENC_DVI_SETTING 0x1b62
> +#define VENC_C656_CTRL 0x1b63
> +#define VENC_UPSAMPLE_CTRL0 0x1b64
> +#define VENC_UPSAMPLE_CTRL1 0x1b65
> +#define VENC_UPSAMPLE_CTRL2 0x1b66
> +#define TCON_INVERT_CTL 0x1b67
> +#define VENC_VIDEO_PROG_MODE 0x1b68
> +#define VENC_ENCI_LINE 0x1b69
> +#define VENC_ENCI_PIXEL 0x1b6a
> +#define VENC_ENCP_LINE 0x1b6b
> +#define VENC_ENCP_PIXEL 0x1b6c
> +#define VENC_STATA 0x1b6d
> +#define VENC_INTCTRL 0x1b6e
> +#define VENC_INTFLAG 0x1b6f
> +#define VENC_VIDEO_TST_EN 0x1b70
> +#define VENC_VIDEO_TST_MDSEL 0x1b71
> +#define VENC_VIDEO_TST_Y 0x1b72
> +#define VENC_VIDEO_TST_CB 0x1b73
> +#define VENC_VIDEO_TST_CR 0x1b74
> +#define VENC_VIDEO_TST_CLRBAR_STRT 0x1b75
> +#define VENC_VIDEO_TST_CLRBAR_WIDTH 0x1b76
> +#define VENC_VIDEO_TST_VDCNT_STSET 0x1b77
> +#define VENC_VDAC_DACSEL0 0x1b78
> +#define VENC_VDAC_DACSEL1 0x1b79
> +#define VENC_VDAC_DACSEL2 0x1b7a
> +#define VENC_VDAC_DACSEL3 0x1b7b
> +#define VENC_VDAC_DACSEL4 0x1b7c
> +#define VENC_VDAC_DACSEL5 0x1b7d
> +#define VENC_VDAC_SETTING 0x1b7e
> +#define VENC_VDAC_TST_VAL 0x1b7f
> +#define VENC_VDAC_DAC0_GAINCTRL 0x1bf0
> +#define VENC_VDAC_DAC0_OFFSET 0x1bf1
> +#define VENC_VDAC_DAC1_GAINCTRL 0x1bf2
> +#define VENC_VDAC_DAC1_OFFSET 0x1bf3
> +#define VENC_VDAC_DAC2_GAINCTRL 0x1bf4
> +#define VENC_VDAC_DAC2_OFFSET 0x1bf5
> +#define VENC_VDAC_DAC3_GAINCTRL 0x1bf6
> +#define VENC_VDAC_DAC3_OFFSET 0x1bf7
> +#define VENC_VDAC_DAC4_GAINCTRL 0x1bf8
> +#define VENC_VDAC_DAC4_OFFSET 0x1bf9
> +#define VENC_VDAC_DAC5_GAINCTRL 0x1bfa
> +#define VENC_VDAC_DAC5_OFFSET 0x1bfb
> +#define VENC_VDAC_FIFO_CTRL 0x1bfc
> +#define ENCL_TCON_INVERT_CTL 0x1bfd
> +#define ENCP_VIDEO_EN 0x1b80
> +#define ENCP_VIDEO_SYNC_MODE 0x1b81
> +#define ENCP_MACV_EN 0x1b82
> +#define ENCP_VIDEO_Y_SCL 0x1b83
> +#define ENCP_VIDEO_PB_SCL 0x1b84
> +#define ENCP_VIDEO_PR_SCL 0x1b85
> +#define ENCP_VIDEO_SYNC_SCL 0x1b86
> +#define ENCP_VIDEO_MACV_SCL 0x1b87
> +#define ENCP_VIDEO_Y_OFFST 0x1b88
> +#define ENCP_VIDEO_PB_OFFST 0x1b89
> +#define ENCP_VIDEO_PR_OFFST 0x1b8a
> +#define ENCP_VIDEO_SYNC_OFFST 0x1b8b
> +#define ENCP_VIDEO_MACV_OFFST 0x1b8c
> +#define ENCP_VIDEO_MODE 0x1b8d
> +#define ENCP_VIDEO_MODE_ADV 0x1b8e
> +#define ENCP_DBG_PX_RST 0x1b90
> +#define ENCP_DBG_LN_RST 0x1b91
> +#define ENCP_DBG_PX_INT 0x1b92
> +#define ENCP_DBG_LN_INT 0x1b93
> +#define ENCP_VIDEO_YFP1_HTIME 0x1b94
> +#define ENCP_VIDEO_YFP2_HTIME 0x1b95
> +#define ENCP_VIDEO_YC_DLY 0x1b96
> +#define ENCP_VIDEO_MAX_PXCNT 0x1b97
> +#define ENCP_VIDEO_HSPULS_BEGIN 0x1b98
> +#define ENCP_VIDEO_HSPULS_END 0x1b99
> +#define ENCP_VIDEO_HSPULS_SWITCH 0x1b9a
> +#define ENCP_VIDEO_VSPULS_BEGIN 0x1b9b
> +#define ENCP_VIDEO_VSPULS_END 0x1b9c
> +#define ENCP_VIDEO_VSPULS_BLINE 0x1b9d
> +#define ENCP_VIDEO_VSPULS_ELINE 0x1b9e
> +#define ENCP_VIDEO_EQPULS_BEGIN 0x1b9f
> +#define ENCP_VIDEO_EQPULS_END 0x1ba0
> +#define ENCP_VIDEO_EQPULS_BLINE 0x1ba1
> +#define ENCP_VIDEO_EQPULS_ELINE 0x1ba2
> +#define ENCP_VIDEO_HAVON_END 0x1ba3
> +#define ENCP_VIDEO_HAVON_BEGIN 0x1ba4
> +#define ENCP_VIDEO_VAVON_ELINE 0x1baf
> +#define ENCP_VIDEO_VAVON_BLINE 0x1ba6
> +#define ENCP_VIDEO_HSO_BEGIN 0x1ba7
> +#define ENCP_VIDEO_HSO_END 0x1ba8
> +#define ENCP_VIDEO_VSO_BEGIN 0x1ba9
> +#define ENCP_VIDEO_VSO_END 0x1baa
> +#define ENCP_VIDEO_VSO_BLINE 0x1bab
> +#define ENCP_VIDEO_VSO_ELINE 0x1bac
> +#define ENCP_VIDEO_SYNC_WAVE_CURVE 0x1bad
> +#define ENCP_VIDEO_MAX_LNCNT 0x1bae
> +#define ENCP_VIDEO_SY_VAL 0x1bb0
> +#define ENCP_VIDEO_SY2_VAL 0x1bb1
> +#define ENCP_VIDEO_BLANKY_VAL 0x1bb2
> +#define ENCP_VIDEO_BLANKPB_VAL 0x1bb3
> +#define ENCP_VIDEO_BLANKPR_VAL 0x1bb4
> +#define ENCP_VIDEO_HOFFST 0x1bb5
> +#define ENCP_VIDEO_VOFFST 0x1bb6
> +#define ENCP_VIDEO_RGB_CTRL 0x1bb7
> +#define ENCP_VIDEO_FILT_CTRL 0x1bb8
> +#define ENCP_VIDEO_OFLD_VPEQ_OFST 0x1bb9
> +#define ENCP_VIDEO_OFLD_VOAV_OFST 0x1bba
> +#define ENCP_VIDEO_MATRIX_CB 0x1bbb
> +#define ENCP_VIDEO_MATRIX_CR 0x1bbc
> +#define ENCP_VIDEO_RGBIN_CTRL 0x1bbd
> +#define ENCP_MACV_BLANKY_VAL 0x1bc0
> +#define ENCP_MACV_MAXY_VAL 0x1bc1
> +#define ENCP_MACV_1ST_PSSYNC_STRT 0x1bc2
> +#define ENCP_MACV_PSSYNC_STRT 0x1bc3
> +#define ENCP_MACV_AGC_STRT 0x1bc4
> +#define ENCP_MACV_AGC_END 0x1bc5
> +#define ENCP_MACV_WAVE_END 0x1bc6
> +#define ENCP_MACV_STRTLINE 0x1bc7
> +#define ENCP_MACV_ENDLINE 0x1bc8
> +#define ENCP_MACV_TS_CNT_MAX_L 0x1bc9
> +#define ENCP_MACV_TS_CNT_MAX_H 0x1bca
> +#define ENCP_MACV_TIME_DOWN 0x1bcb
> +#define ENCP_MACV_TIME_LO 0x1bcc
> +#define ENCP_MACV_TIME_UP 0x1bcd
> +#define ENCP_MACV_TIME_RST 0x1bce
> +#define ENCP_VBI_CTRL 0x1bd0
> +#define ENCP_VBI_SETTING 0x1bd1
> +#define ENCP_VBI_BEGIN 0x1bd2
> +#define ENCP_VBI_WIDTH 0x1bd3
> +#define ENCP_VBI_HVAL 0x1bd4
> +#define ENCP_VBI_DATA0 0x1bd5
> +#define ENCP_VBI_DATA1 0x1bd6
> +#define C656_HS_ST 0x1be0
> +#define C656_HS_ED 0x1be1
> +#define C656_VS_LNST_E 0x1be2
> +#define C656_VS_LNST_O 0x1be3
> +#define C656_VS_LNED_E 0x1be4
> +#define C656_VS_LNED_O 0x1be5
> +#define C656_FS_LNST 0x1be6
> +#define C656_FS_LNED 0x1be7
> +#define ENCI_VIDEO_MODE 0x1b00
> +#define ENCI_VIDEO_MODE_ADV 0x1b01
> +#define ENCI_VIDEO_FSC_ADJ 0x1b02
> +#define ENCI_VIDEO_BRIGHT 0x1b03
> +#define ENCI_VIDEO_CONT 0x1b04
> +#define ENCI_VIDEO_SAT 0x1b05
> +#define ENCI_VIDEO_HUE 0x1b06
> +#define ENCI_VIDEO_SCH 0x1b07
> +#define ENCI_SYNC_MODE 0x1b08
> +#define ENCI_SYNC_CTRL 0x1b09
> +#define ENCI_SYNC_HSO_BEGIN 0x1b0a
> +#define ENCI_SYNC_HSO_END 0x1b0b
> +#define ENCI_SYNC_VSO_EVN 0x1b0c
> +#define ENCI_SYNC_VSO_ODD 0x1b0d
> +#define ENCI_SYNC_VSO_EVNLN 0x1b0e
> +#define ENCI_SYNC_VSO_ODDLN 0x1b0f
> +#define ENCI_SYNC_HOFFST 0x1b10
> +#define ENCI_SYNC_VOFFST 0x1b11
> +#define ENCI_SYNC_ADJ 0x1b12
> +#define ENCI_RGB_SETTING 0x1b13
> +#define ENCI_DE_H_BEGIN 0x1b16
> +#define ENCI_DE_H_END 0x1b17
> +#define ENCI_DE_V_BEGIN_EVEN 0x1b18
> +#define ENCI_DE_V_END_EVEN 0x1b19
> +#define ENCI_DE_V_BEGIN_ODD 0x1b1a
> +#define ENCI_DE_V_END_ODD 0x1b1b
> +#define ENCI_VBI_SETTING 0x1b20
> +#define ENCI_VBI_CCDT_EVN 0x1b21
> +#define ENCI_VBI_CCDT_ODD 0x1b22
> +#define ENCI_VBI_CC525_LN 0x1b23
> +#define ENCI_VBI_CC625_LN 0x1b24
> +#define ENCI_VBI_WSSDT 0x1b25
> +#define ENCI_VBI_WSS_LN 0x1b26
> +#define ENCI_VBI_CGMSDT_L 0x1b27
> +#define ENCI_VBI_CGMSDT_H 0x1b28
> +#define ENCI_VBI_CGMS_LN 0x1b29
> +#define ENCI_VBI_TTX_HTIME 0x1b2a
> +#define ENCI_VBI_TTX_LN 0x1b2b
> +#define ENCI_VBI_TTXDT0 0x1b2c
> +#define ENCI_VBI_TTXDT1 0x1b2d
> +#define ENCI_VBI_TTXDT2 0x1b2e
> +#define ENCI_VBI_TTXDT3 0x1b2f
> +#define ENCI_MACV_N0 0x1b30
> +#define ENCI_MACV_N1 0x1b31
> +#define ENCI_MACV_N2 0x1b32
> +#define ENCI_MACV_N3 0x1b33
> +#define ENCI_MACV_N4 0x1b34
> +#define ENCI_MACV_N5 0x1b35
> +#define ENCI_MACV_N6 0x1b36
> +#define ENCI_MACV_N7 0x1b37
> +#define ENCI_MACV_N8 0x1b38
> +#define ENCI_MACV_N9 0x1b39
> +#define ENCI_MACV_N10 0x1b3a
> +#define ENCI_MACV_N11 0x1b3b
> +#define ENCI_MACV_N12 0x1b3c
> +#define ENCI_MACV_N13 0x1b3d
> +#define ENCI_MACV_N14 0x1b3e
> +#define ENCI_MACV_N15 0x1b3f
> +#define ENCI_MACV_N16 0x1b40
> +#define ENCI_MACV_N17 0x1b41
> +#define ENCI_MACV_N18 0x1b42
> +#define ENCI_MACV_N19 0x1b43
> +#define ENCI_MACV_N20 0x1b44
> +#define ENCI_MACV_N21 0x1b45
> +#define ENCI_MACV_N22 0x1b46
> +#define ENCI_DBG_PX_RST 0x1b48
> +#define ENCI_DBG_FLDLN_RST 0x1b49
> +#define ENCI_DBG_PX_INT 0x1b4a
> +#define ENCI_DBG_FLDLN_INT 0x1b4b
> +#define ENCI_DBG_MAXPX 0x1b4c
> +#define ENCI_DBG_MAXLN 0x1b4d
> +#define ENCI_MACV_MAX_AMP 0x1b50
> +#define ENCI_MACV_PULSE_LO 0x1b51
> +#define ENCI_MACV_PULSE_HI 0x1b52
> +#define ENCI_MACV_BKP_MAX 0x1b53
> +#define ENCI_CFILT_CTRL 0x1b54
> +#define ENCI_CFILT7 0x1b55
> +#define ENCI_YC_DELAY 0x1b56
> +#define ENCI_VIDEO_EN 0x1b57
> +#define ENCI_DVI_HSO_BEGIN 0x1c00
> +#define ENCI_DVI_HSO_END 0x1c01
> +#define ENCI_DVI_VSO_BLINE_EVN 0x1c02
> +#define ENCI_DVI_VSO_BLINE_ODD 0x1c03
> +#define ENCI_DVI_VSO_ELINE_EVN 0x1c04
> +#define ENCI_DVI_VSO_ELINE_ODD 0x1c05
> +#define ENCI_DVI_VSO_BEGIN_EVN 0x1c06
> +#define ENCI_DVI_VSO_BEGIN_ODD 0x1c07
> +#define ENCI_DVI_VSO_END_EVN 0x1c08
> +#define ENCI_DVI_VSO_END_ODD 0x1c09
> +#define ENCI_CFILT_CTRL2 0x1c0a
> +#define ENCI_DACSEL_0 0x1c0b
> +#define ENCI_DACSEL_1 0x1c0c
> +#define ENCP_DACSEL_0 0x1c0d
> +#define ENCP_DACSEL_1 0x1c0e
> +#define ENCP_MAX_LINE_SWITCH_POINT 0x1c0f
> +#define ENCI_TST_EN 0x1c10
> +#define ENCI_TST_MDSEL 0x1c11
> +#define ENCI_TST_Y 0x1c12
> +#define ENCI_TST_CB 0x1c13
> +#define ENCI_TST_CR 0x1c14
> +#define ENCI_TST_CLRBAR_STRT 0x1c15
> +#define ENCI_TST_CLRBAR_WIDTH 0x1c16
> +#define ENCI_TST_VDCNT_STSET 0x1c17
> +#define ENCI_VFIFO2VD_CTL 0x1c18
> +#define ENCI_VFIFO2VD_PIXEL_START 0x1c19
> +#define ENCI_VFIFO2VD_PIXEL_END 0x1c1a
> +#define ENCI_VFIFO2VD_LINE_TOP_START 0x1c1b
> +#define ENCI_VFIFO2VD_LINE_TOP_END 0x1c1c
> +#define ENCI_VFIFO2VD_LINE_BOT_START 0x1c1d
> +#define ENCI_VFIFO2VD_LINE_BOT_END 0x1c1e
> +#define ENCI_VFIFO2VD_CTL2 0x1c1f
> +#define ENCT_VFIFO2VD_CTL 0x1c20
> +#define ENCT_VFIFO2VD_PIXEL_START 0x1c21
> +#define ENCT_VFIFO2VD_PIXEL_END 0x1c22
> +#define ENCT_VFIFO2VD_LINE_TOP_START 0x1c23
> +#define ENCT_VFIFO2VD_LINE_TOP_END 0x1c24
> +#define ENCT_VFIFO2VD_LINE_BOT_START 0x1c25
> +#define ENCT_VFIFO2VD_LINE_BOT_END 0x1c26
> +#define ENCT_VFIFO2VD_CTL2 0x1c27
> +#define ENCT_TST_EN 0x1c28
> +#define ENCT_TST_MDSEL 0x1c29
> +#define ENCT_TST_Y 0x1c2a
> +#define ENCT_TST_CB 0x1c2b
> +#define ENCT_TST_CR 0x1c2c
> +#define ENCT_TST_CLRBAR_STRT 0x1c2d
> +#define ENCT_TST_CLRBAR_WIDTH 0x1c2e
> +#define ENCT_TST_VDCNT_STSET 0x1c2f
> +#define ENCP_DVI_HSO_BEGIN 0x1c30
> +#define ENCP_DVI_HSO_END 0x1c31
> +#define ENCP_DVI_VSO_BLINE_EVN 0x1c32
> +#define ENCP_DVI_VSO_BLINE_ODD 0x1c33
> +#define ENCP_DVI_VSO_ELINE_EVN 0x1c34
> +#define ENCP_DVI_VSO_ELINE_ODD 0x1c35
> +#define ENCP_DVI_VSO_BEGIN_EVN 0x1c36
> +#define ENCP_DVI_VSO_BEGIN_ODD 0x1c37
> +#define ENCP_DVI_VSO_END_EVN 0x1c38
> +#define ENCP_DVI_VSO_END_ODD 0x1c39
> +#define ENCP_DE_H_BEGIN 0x1c3a
> +#define ENCP_DE_H_END 0x1c3b
> +#define ENCP_DE_V_BEGIN_EVEN 0x1c3c
> +#define ENCP_DE_V_END_EVEN 0x1c3d
> +#define ENCP_DE_V_BEGIN_ODD 0x1c3e
> +#define ENCP_DE_V_END_ODD 0x1c3f
> +#define ENCI_SYNC_LINE_LENGTH 0x1c40
> +#define ENCI_SYNC_PIXEL_EN 0x1c41
> +#define ENCI_SYNC_TO_LINE_EN 0x1c42
> +#define ENCI_SYNC_TO_PIXEL 0x1c43
> +#define ENCP_SYNC_LINE_LENGTH 0x1c44
> +#define ENCP_SYNC_PIXEL_EN 0x1c45
> +#define ENCP_SYNC_TO_LINE_EN 0x1c46
> +#define ENCP_SYNC_TO_PIXEL 0x1c47
> +#define ENCT_SYNC_LINE_LENGTH 0x1c48
> +#define ENCT_SYNC_PIXEL_EN 0x1c49
> +#define ENCT_SYNC_TO_LINE_EN 0x1c4a
> +#define ENCT_SYNC_TO_PIXEL 0x1c4b
> +#define ENCL_SYNC_LINE_LENGTH 0x1c4c
> +#define ENCL_SYNC_PIXEL_EN 0x1c4d
> +#define ENCL_SYNC_TO_LINE_EN 0x1c4e
> +#define ENCL_SYNC_TO_PIXEL 0x1c4f
> +#define ENCP_VFIFO2VD_CTL2 0x1c50
> +#define VENC_DVI_SETTING_MORE 0x1c51
> +#define VENC_VDAC_DAC4_FILT_CTRL0 0x1c54
> +#define VENC_VDAC_DAC4_FILT_CTRL1 0x1c55
> +#define VENC_VDAC_DAC5_FILT_CTRL0 0x1c56
> +#define VENC_VDAC_DAC5_FILT_CTRL1 0x1c57
> +#define VENC_VDAC_DAC0_FILT_CTRL0 0x1c58
> +#define VENC_VDAC_DAC0_FILT_CTRL1 0x1c59
> +#define VENC_VDAC_DAC1_FILT_CTRL0 0x1c5a
> +#define VENC_VDAC_DAC1_FILT_CTRL1 0x1c5b
> +#define VENC_VDAC_DAC2_FILT_CTRL0 0x1c5c
> +#define VENC_VDAC_DAC2_FILT_CTRL1 0x1c5d
> +#define VENC_VDAC_DAC3_FILT_CTRL0 0x1c5e
> +#define VENC_VDAC_DAC3_FILT_CTRL1 0x1c5f
> +#define ENCT_VIDEO_EN 0x1c60
> +#define ENCT_VIDEO_Y_SCL 0x1c61
> +#define ENCT_VIDEO_PB_SCL 0x1c62
> +#define ENCT_VIDEO_PR_SCL 0x1c63
> +#define ENCT_VIDEO_Y_OFFST 0x1c64
> +#define ENCT_VIDEO_PB_OFFST 0x1c65
> +#define ENCT_VIDEO_PR_OFFST 0x1c66
> +#define ENCT_VIDEO_MODE 0x1c67
> +#define ENCT_VIDEO_MODE_ADV 0x1c68
> +#define ENCT_DBG_PX_RST 0x1c69
> +#define ENCT_DBG_LN_RST 0x1c6a
> +#define ENCT_DBG_PX_INT 0x1c6b
> +#define ENCT_DBG_LN_INT 0x1c6c
> +#define ENCT_VIDEO_YFP1_HTIME 0x1c6d
> +#define ENCT_VIDEO_YFP2_HTIME 0x1c6e
> +#define ENCT_VIDEO_YC_DLY 0x1c6f
> +#define ENCT_VIDEO_MAX_PXCNT 0x1c70
> +#define ENCT_VIDEO_HAVON_END 0x1c71
> +#define ENCT_VIDEO_HAVON_BEGIN 0x1c72
> +#define ENCT_VIDEO_VAVON_ELINE 0x1c73
> +#define ENCT_VIDEO_VAVON_BLINE 0x1c74
> +#define ENCT_VIDEO_HSO_BEGIN 0x1c75
> +#define ENCT_VIDEO_HSO_END 0x1c76
> +#define ENCT_VIDEO_VSO_BEGIN 0x1c77
> +#define ENCT_VIDEO_VSO_END 0x1c78
> +#define ENCT_VIDEO_VSO_BLINE 0x1c79
> +#define ENCT_VIDEO_VSO_ELINE 0x1c7a
> +#define ENCT_VIDEO_MAX_LNCNT 0x1c7b
> +#define ENCT_VIDEO_BLANKY_VAL 0x1c7c
> +#define ENCT_VIDEO_BLANKPB_VAL 0x1c7d
> +#define ENCT_VIDEO_BLANKPR_VAL 0x1c7e
> +#define ENCT_VIDEO_HOFFST 0x1c7f
> +#define ENCT_VIDEO_VOFFST 0x1c80
> +#define ENCT_VIDEO_RGB_CTRL 0x1c81
> +#define ENCT_VIDEO_FILT_CTRL 0x1c82
> +#define ENCT_VIDEO_OFLD_VPEQ_OFST 0x1c83
> +#define ENCT_VIDEO_OFLD_VOAV_OFST 0x1c84
> +#define ENCT_VIDEO_MATRIX_CB 0x1c85
> +#define ENCT_VIDEO_MATRIX_CR 0x1c86
> +#define ENCT_VIDEO_RGBIN_CTRL 0x1c87
> +#define ENCT_MAX_LINE_SWITCH_POINT 0x1c88
> +#define ENCT_DACSEL_0 0x1c89
> +#define ENCT_DACSEL_1 0x1c8a
> +#define ENCL_VFIFO2VD_CTL 0x1c90
> +#define ENCL_VFIFO2VD_PIXEL_START 0x1c91
> +#define ENCL_VFIFO2VD_PIXEL_END 0x1c92
> +#define ENCL_VFIFO2VD_LINE_TOP_START 0x1c93
> +#define ENCL_VFIFO2VD_LINE_TOP_END 0x1c94
> +#define ENCL_VFIFO2VD_LINE_BOT_START 0x1c95
> +#define ENCL_VFIFO2VD_LINE_BOT_END 0x1c96
> +#define ENCL_VFIFO2VD_CTL2 0x1c97
> +#define ENCL_TST_EN 0x1c98
> +#define ENCL_TST_MDSEL 0x1c99
> +#define ENCL_TST_Y 0x1c9a
> +#define ENCL_TST_CB 0x1c9b
> +#define ENCL_TST_CR 0x1c9c
> +#define ENCL_TST_CLRBAR_STRT 0x1c9d
> +#define ENCL_TST_CLRBAR_WIDTH 0x1c9e
> +#define ENCL_TST_VDCNT_STSET 0x1c9f
> +#define ENCL_VIDEO_EN 0x1ca0
> +#define ENCL_VIDEO_Y_SCL 0x1ca1
> +#define ENCL_VIDEO_PB_SCL 0x1ca2
> +#define ENCL_VIDEO_PR_SCL 0x1ca3
> +#define ENCL_VIDEO_Y_OFFST 0x1ca4
> +#define ENCL_VIDEO_PB_OFFST 0x1ca5
> +#define ENCL_VIDEO_PR_OFFST 0x1ca6
> +#define ENCL_VIDEO_MODE 0x1ca7
> +#define ENCL_VIDEO_MODE_ADV 0x1ca8
> +#define ENCL_DBG_PX_RST 0x1ca9
> +#define ENCL_DBG_LN_RST 0x1caa
> +#define ENCL_DBG_PX_INT 0x1cab
> +#define ENCL_DBG_LN_INT 0x1cac
> +#define ENCL_VIDEO_YFP1_HTIME 0x1cad
> +#define ENCL_VIDEO_YFP2_HTIME 0x1cae
> +#define ENCL_VIDEO_YC_DLY 0x1caf
> +#define ENCL_VIDEO_MAX_PXCNT 0x1cb0
> +#define ENCL_VIDEO_HAVON_END 0x1cb1
> +#define ENCL_VIDEO_HAVON_BEGIN 0x1cb2
> +#define ENCL_VIDEO_VAVON_ELINE 0x1cb3
> +#define ENCL_VIDEO_VAVON_BLINE 0x1cb4
> +#define ENCL_VIDEO_HSO_BEGIN 0x1cb5
> +#define ENCL_VIDEO_HSO_END 0x1cb6
> +#define ENCL_VIDEO_VSO_BEGIN 0x1cb7
> +#define ENCL_VIDEO_VSO_END 0x1cb8
> +#define ENCL_VIDEO_VSO_BLINE 0x1cb9
> +#define ENCL_VIDEO_VSO_ELINE 0x1cba
> +#define ENCL_VIDEO_MAX_LNCNT 0x1cbb
> +#define ENCL_VIDEO_BLANKY_VAL 0x1cbc
> +#define ENCL_VIDEO_BLANKPB_VAL 0x1cbd
> +#define ENCL_VIDEO_BLANKPR_VAL 0x1cbe
> +#define ENCL_VIDEO_HOFFST 0x1cbf
> +#define ENCL_VIDEO_VOFFST 0x1cc0
> +#define ENCL_VIDEO_RGB_CTRL 0x1cc1
> +#define ENCL_VIDEO_FILT_CTRL 0x1cc2
> +#define ENCL_VIDEO_OFLD_VPEQ_OFST 0x1cc3
> +#define ENCL_VIDEO_OFLD_VOAV_OFST 0x1cc4
> +#define ENCL_VIDEO_MATRIX_CB 0x1cc5
> +#define ENCL_VIDEO_MATRIX_CR 0x1cc6
> +#define ENCL_VIDEO_RGBIN_CTRL 0x1cc7
> +#define ENCL_MAX_LINE_SWITCH_POINT 0x1cc8
> +#define ENCL_DACSEL_0 0x1cc9
> +#define ENCL_DACSEL_1 0x1cca
> +#define RDMA_AHB_START_ADDR_MAN 0x1100
> +#define RDMA_AHB_END_ADDR_MAN 0x1101
> +#define RDMA_AHB_START_ADDR_1 0x1102
> +#define RDMA_AHB_END_ADDR_1 0x1103
> +#define RDMA_AHB_START_ADDR_2 0x1104
> +#define RDMA_AHB_END_ADDR_2 0x1105
> +#define RDMA_AHB_START_ADDR_3 0x1106
> +#define RDMA_AHB_END_ADDR_3 0x1107
> +#define RDMA_AHB_START_ADDR_4 0x1108
> +#define RDMA_AHB_END_ADDR_4 0x1109
> +#define RDMA_AHB_START_ADDR_5 0x110a
> +#define RDMA_AHB_END_ADDR_5 0x110b
> +#define RDMA_AHB_START_ADDR_6 0x110c
> +#define RDMA_AHB_END_ADDR_6 0x110d
> +#define RDMA_AHB_START_ADDR_7 0x110e
> +#define RDMA_AHB_END_ADDR_7 0x110f
> +#define RDMA_ACCESS_AUTO 0x1110
> +#define RDMA_ACCESS_AUTO2 0x1111
> +#define RDMA_ACCESS_AUTO3 0x1112
> +#define RDMA_ACCESS_MAN 0x1113
> +#define RDMA_CTRL 0x1114
> +#define RDMA_STATUS 0x1115
> +#define RDMA_STATUS2 0x1116
> +#define RDMA_STATUS3 0x1117
> +#define L_GAMMA_CNTL_PORT 0x1400
> +#define L_GAMMA_DATA_PORT 0x1401
> +#define L_GAMMA_ADDR_PORT 0x1402
> +#define L_GAMMA_VCOM_HSWITCH_ADDR 0x1403
> +#define L_RGB_BASE_ADDR 0x1405
> +#define L_RGB_COEFF_ADDR 0x1406
> +#define L_POL_CNTL_ADDR 0x1407
> +#define L_DITH_CNTL_ADDR 0x1408
> +#define L_GAMMA_PROBE_CTRL 0x1409
> +#define L_GAMMA_PROBE_COLOR_L 0x140a
> +#define L_GAMMA_PROBE_COLOR_H 0x140b
> +#define L_GAMMA_PROBE_HL_COLOR 0x140c
> +#define L_GAMMA_PROBE_POS_X 0x140d
> +#define L_GAMMA_PROBE_POS_Y 0x140e
> +#define L_STH1_HS_ADDR 0x1410
> +#define L_STH1_HE_ADDR 0x1411
> +#define L_STH1_VS_ADDR 0x1412
> +#define L_STH1_VE_ADDR 0x1413
> +#define L_STH2_HS_ADDR 0x1414
> +#define L_STH2_HE_ADDR 0x1415
> +#define L_STH2_VS_ADDR 0x1416
> +#define L_STH2_VE_ADDR 0x1417
> +#define L_OEH_HS_ADDR 0x1418
> +#define L_OEH_HE_ADDR 0x1419
> +#define L_OEH_VS_ADDR 0x141a
> +#define L_OEH_VE_ADDR 0x141b
> +#define L_VCOM_HSWITCH_ADDR 0x141c
> +#define L_VCOM_VS_ADDR 0x141d
> +#define L_VCOM_VE_ADDR 0x141e
> +#define L_CPV1_HS_ADDR 0x141f
> +#define L_CPV1_HE_ADDR 0x1420
> +#define L_CPV1_VS_ADDR 0x1421
> +#define L_CPV1_VE_ADDR 0x1422
> +#define L_CPV2_HS_ADDR 0x1423
> +#define L_CPV2_HE_ADDR 0x1424
> +#define L_CPV2_VS_ADDR 0x1425
> +#define L_CPV2_VE_ADDR 0x1426
> +#define L_STV1_HS_ADDR 0x1427
> +#define L_STV1_HE_ADDR 0x1428
> +#define L_STV1_VS_ADDR 0x1429
> +#define L_STV1_VE_ADDR 0x142a
> +#define L_STV2_HS_ADDR 0x142b
> +#define L_STV2_HE_ADDR 0x142c
> +#define L_STV2_VS_ADDR 0x142d
> +#define L_STV2_VE_ADDR 0x142e
> +#define L_OEV1_HS_ADDR 0x142f
> +#define L_OEV1_HE_ADDR 0x1430
> +#define L_OEV1_VS_ADDR 0x1431
> +#define L_OEV1_VE_ADDR 0x1432
> +#define L_OEV2_HS_ADDR 0x1433
> +#define L_OEV2_HE_ADDR 0x1434
> +#define L_OEV2_VS_ADDR 0x1435
> +#define L_OEV2_VE_ADDR 0x1436
> +#define L_OEV3_HS_ADDR 0x1437
> +#define L_OEV3_HE_ADDR 0x1438
> +#define L_OEV3_VS_ADDR 0x1439
> +#define L_OEV3_VE_ADDR 0x143a
> +#define L_LCD_PWR_ADDR 0x143b
> +#define L_LCD_PWM0_LO_ADDR 0x143c
> +#define L_LCD_PWM0_HI_ADDR 0x143d
> +#define L_LCD_PWM1_LO_ADDR 0x143e
> +#define L_LCD_PWM1_HI_ADDR 0x143f
> +#define L_INV_CNT_ADDR 0x1440
> +#define L_TCON_MISC_SEL_ADDR 0x1441
> +#define L_DUAL_PORT_CNTL_ADDR 0x1442
> +#define MLVDS_CLK_CTL1_HI 0x1443
> +#define MLVDS_CLK_CTL1_LO 0x1444
> +#define L_TCON_DOUBLE_CTL 0x1449
> +#define L_TCON_PATTERN_HI 0x144a
> +#define L_TCON_PATTERN_LO 0x144b
> +#define LDIM_BL_ADDR_PORT 0x144e
> +#define LDIM_BL_DATA_PORT 0x144f
> +#define L_DE_HS_ADDR 0x1451
> +#define L_DE_HE_ADDR 0x1452
> +#define L_DE_VS_ADDR 0x1453
> +#define L_DE_VE_ADDR 0x1454
> +#define L_HSYNC_HS_ADDR 0x1455
> +#define L_HSYNC_HE_ADDR 0x1456
> +#define L_HSYNC_VS_ADDR 0x1457
> +#define L_HSYNC_VE_ADDR 0x1458
> +#define L_VSYNC_HS_ADDR 0x1459
> +#define L_VSYNC_HE_ADDR 0x145a
> +#define L_VSYNC_VS_ADDR 0x145b
> +#define L_VSYNC_VE_ADDR 0x145c
> +#define L_LCD_MCU_CTL 0x145d
> +#define DUAL_MLVDS_CTL 0x1460
> +#define DUAL_MLVDS_LINE_START 0x1461
> +#define DUAL_MLVDS_LINE_END 0x1462
> +#define DUAL_MLVDS_PIXEL_W_START_L 0x1463
> +#define DUAL_MLVDS_PIXEL_W_END_L 0x1464
> +#define DUAL_MLVDS_PIXEL_W_START_R 0x1465
> +#define DUAL_MLVDS_PIXEL_W_END_R 0x1466
> +#define DUAL_MLVDS_PIXEL_R_START_L 0x1467
> +#define DUAL_MLVDS_PIXEL_R_CNT_L 0x1468
> +#define DUAL_MLVDS_PIXEL_R_START_R 0x1469
> +#define DUAL_MLVDS_PIXEL_R_CNT_R 0x146a
> +#define V_INVERSION_PIXEL 0x1470
> +#define V_INVERSION_LINE 0x1471
> +#define V_INVERSION_CONTROL 0x1472
> +#define MLVDS2_CONTROL 0x1474
> +#define MLVDS2_CONFIG_HI 0x1475
> +#define MLVDS2_CONFIG_LO 0x1476
> +#define MLVDS2_DUAL_GATE_WR_START 0x1477
> +#define MLVDS2_DUAL_GATE_WR_END 0x1478
> +#define MLVDS2_DUAL_GATE_RD_START 0x1479
> +#define MLVDS2_DUAL_GATE_RD_END 0x147a
> +#define MLVDS2_SECOND_RESET_CTL 0x147b
> +#define MLVDS2_DUAL_GATE_CTL_HI 0x147c
> +#define MLVDS2_DUAL_GATE_CTL_LO 0x147d
> +#define MLVDS2_RESET_CONFIG_HI 0x147e
> +#define MLVDS2_RESET_CONFIG_LO 0x147f
> +#define GAMMA_CNTL_PORT 0x1480
> +#define GAMMA_DATA_PORT 0x1481
> +#define GAMMA_ADDR_PORT 0x1482
> +#define GAMMA_VCOM_HSWITCH_ADDR 0x1483
> +#define RGB_BASE_ADDR 0x1485
> +#define RGB_COEFF_ADDR 0x1486
> +#define POL_CNTL_ADDR 0x1487
> +#define DITH_CNTL_ADDR 0x1488
> +#define GAMMA_PROBE_CTRL 0x1489
> +#define GAMMA_PROBE_COLOR_L 0x148a
> +#define GAMMA_PROBE_COLOR_H 0x148b
> +#define GAMMA_PROBE_HL_COLOR 0x148c
> +#define GAMMA_PROBE_POS_X 0x148d
> +#define GAMMA_PROBE_POS_Y 0x148e
> +#define STH1_HS_ADDR 0x1490
> +#define STH1_HE_ADDR 0x1491
> +#define STH1_VS_ADDR 0x1492
> +#define STH1_VE_ADDR 0x1493
> +#define STH2_HS_ADDR 0x1494
> +#define STH2_HE_ADDR 0x1495
> +#define STH2_VS_ADDR 0x1496
> +#define STH2_VE_ADDR 0x1497
> +#define OEH_HS_ADDR 0x1498
> +#define OEH_HE_ADDR 0x1499
> +#define OEH_VS_ADDR 0x149a
> +#define OEH_VE_ADDR 0x149b
> +#define VCOM_HSWITCH_ADDR 0x149c
> +#define VCOM_VS_ADDR 0x149d
> +#define VCOM_VE_ADDR 0x149e
> +#define CPV1_HS_ADDR 0x149f
> +#define CPV1_HE_ADDR 0x14a0
> +#define CPV1_VS_ADDR 0x14a1
> +#define CPV1_VE_ADDR 0x14a2
> +#define CPV2_HS_ADDR 0x14a3
> +#define CPV2_HE_ADDR 0x14a4
> +#define CPV2_VS_ADDR 0x14a5
> +#define CPV2_VE_ADDR 0x14a6
> +#define STV1_HS_ADDR 0x14a7
> +#define STV1_HE_ADDR 0x14a8
> +#define STV1_VS_ADDR 0x14a9
> +#define STV1_VE_ADDR 0x14aa
> +#define STV2_HS_ADDR 0x14ab
> +#define STV2_HE_ADDR 0x14ac
> +#define STV2_VS_ADDR 0x14ad
> +#define STV2_VE_ADDR 0x14ae
> +#define OEV1_HS_ADDR 0x14af
> +#define OEV1_HE_ADDR 0x14b0
> +#define OEV1_VS_ADDR 0x14b1
> +#define OEV1_VE_ADDR 0x14b2
> +#define OEV2_HS_ADDR 0x14b3
> +#define OEV2_HE_ADDR 0x14b4
> +#define OEV2_VS_ADDR 0x14b5
> +#define OEV2_VE_ADDR 0x14b6
> +#define OEV3_HS_ADDR 0x14b7
> +#define OEV3_HE_ADDR 0x14b8
> +#define OEV3_VS_ADDR 0x14b9
> +#define OEV3_VE_ADDR 0x14ba
> +#define LCD_PWR_ADDR 0x14bb
> +#define LCD_PWM0_LO_ADDR 0x14bc
> +#define LCD_PWM0_HI_ADDR 0x14bd
> +#define LCD_PWM1_LO_ADDR 0x14be
> +#define LCD_PWM1_HI_ADDR 0x14bf
> +#define INV_CNT_ADDR 0x14c0
> +#define TCON_MISC_SEL_ADDR 0x14c1
> +#define DUAL_PORT_CNTL_ADDR 0x14c2
> +#define MLVDS_CONTROL 0x14c3
> +#define MLVDS_RESET_PATTERN_HI 0x14c4
> +#define MLVDS_RESET_PATTERN_LO 0x14c5
> +#define MLVDS_RESET_PATTERN_EXT 0x14c6
> +#define MLVDS_CONFIG_HI 0x14c7
> +#define MLVDS_CONFIG_LO 0x14c8
> +#define TCON_DOUBLE_CTL 0x14c9
> +#define TCON_PATTERN_HI 0x14ca
> +#define TCON_PATTERN_LO 0x14cb
> +#define TCON_CONTROL_HI 0x14cc
> +#define TCON_CONTROL_LO 0x14cd
> +#define LVDS_BLANK_DATA_HI 0x14ce
> +#define LVDS_BLANK_DATA_LO 0x14cf
> +#define LVDS_PACK_CNTL_ADDR 0x14d0
> +#define DE_HS_ADDR 0x14d1
> +#define DE_HE_ADDR 0x14d2
> +#define DE_VS_ADDR 0x14d3
> +#define DE_VE_ADDR 0x14d4
> +#define HSYNC_HS_ADDR 0x14d5
> +#define HSYNC_HE_ADDR 0x14d6
> +#define HSYNC_VS_ADDR 0x14d7
> +#define HSYNC_VE_ADDR 0x14d8
> +#define VSYNC_HS_ADDR 0x14d9
> +#define VSYNC_HE_ADDR 0x14da
> +#define VSYNC_VS_ADDR 0x14db
> +#define VSYNC_VE_ADDR 0x14dc
> +#define LCD_MCU_CTL 0x14dd
> +#define LCD_MCU_DATA_0 0x14de
> +#define LCD_MCU_DATA_1 0x14df
> +#define LVDS_GEN_CNTL 0x14e0
> +#define LVDS_PHY_CNTL0 0x14e1
> +#define LVDS_PHY_CNTL1 0x14e2
> +#define LVDS_PHY_CNTL2 0x14e3
> +#define LVDS_PHY_CNTL3 0x14e4
> +#define LVDS_PHY_CNTL4 0x14e5
> +#define LVDS_PHY_CNTL5 0x14e6
> +#define LVDS_SRG_TEST 0x14e8
> +#define LVDS_BIST_MUX0 0x14e9
> +#define LVDS_BIST_MUX1 0x14ea
> +#define LVDS_BIST_FIXED0 0x14eb
> +#define LVDS_BIST_FIXED1 0x14ec
> +#define LVDS_BIST_CNTL0 0x14ed
> +#define LVDS_CLKB_CLKA 0x14ee
> +#define LVDS_PHY_CLK_CNTL 0x14ef
> +#define LVDS_SER_EN 0x14f0
> +#define LVDS_PHY_CNTL6 0x14f1
> +#define LVDS_PHY_CNTL7 0x14f2
> +#define LVDS_PHY_CNTL8 0x14f3
> +#define MLVDS_CLK_CTL0_HI 0x14f4
> +#define MLVDS_CLK_CTL0_LO 0x14f5
> +#define MLVDS_DUAL_GATE_WR_START 0x14f6
> +#define MLVDS_DUAL_GATE_WR_END 0x14f7
> +#define MLVDS_DUAL_GATE_RD_START 0x14f8
> +#define MLVDS_DUAL_GATE_RD_END 0x14f9
> +#define MLVDS_SECOND_RESET_CTL 0x14fa
> +#define MLVDS_DUAL_GATE_CTL_HI 0x14fb
> +#define MLVDS_DUAL_GATE_CTL_LO 0x14fc
> +#define MLVDS_RESET_CONFIG_HI 0x14fd
> +#define MLVDS_RESET_CONFIG_LO 0x14fe
> +#define VPU_OSD1_MMC_CTRL 0x2701
> +#define VPU_OSD2_MMC_CTRL 0x2702
> +#define VPU_VD1_MMC_CTRL 0x2703
> +#define VPU_VD2_MMC_CTRL 0x2704
> +#define VPU_DI_IF1_MMC_CTRL 0x2705
> +#define VPU_DI_MEM_MMC_CTRL 0x2706
> +#define VPU_DI_INP_MMC_CTRL 0x2707
> +#define VPU_DI_MTNRD_MMC_CTRL 0x2708
> +#define VPU_DI_CHAN2_MMC_CTRL 0x2709
> +#define VPU_DI_MTNWR_MMC_CTRL 0x270a
> +#define VPU_DI_NRWR_MMC_CTRL 0x270b
> +#define VPU_DI_DIWR_MMC_CTRL 0x270c
> +#define VPU_VDIN0_MMC_CTRL 0x270d
> +#define VPU_VDIN1_MMC_CTRL 0x270e
> +#define VPU_BT656_MMC_CTRL 0x270f
> +#define VPU_TVD3D_MMC_CTRL 0x2710
> +#define VPU_TVDVBI_MMC_CTRL 0x2711
> +#define VPU_TVDVBI_VSLATCH_ADDR 0x2712
> +#define VPU_TVDVBI_WRRSP_ADDR 0x2713
> +#define VPU_VDIN_PRE_ARB_CTRL 0x2714
> +#define VPU_VDISP_PRE_ARB_CTRL 0x2715
> +#define VPU_VPUARB2_PRE_ARB_CTRL 0x2716
> +#define VPU_OSD3_MMC_CTRL 0x2717
> +#define VPU_OSD4_MMC_CTRL 0x2718
> +#define VPU_VD3_MMC_CTRL 0x2719
> +#define VPU_VIU_VENC_MUX_CTRL 0x271a
> +#define VIU1_SEL_VENC_MASK 0x3
> +#define VIU1_SEL_VENC_ENCL 0
> +#define VIU1_SEL_VENC_ENCI 1
> +#define VIU1_SEL_VENC_ENCP 2
> +#define VIU1_SEL_VENC_ENCT 3
> +#define VIU2_SEL_VENC_MASK 0xc
> +#define VIU2_SEL_VENC_ENCL 0
> +#define VIU2_SEL_VENC_ENCI (1 << 2)
> +#define VIU2_SEL_VENC_ENCP (2 << 2)
> +#define VIU2_SEL_VENC_ENCT (3 << 2)
> +#define VPU_HDMI_SETTING 0x271b
> +#define ENCI_INFO_READ 0x271c
> +#define ENCP_INFO_READ 0x271d
> +#define ENCT_INFO_READ 0x271e
> +#define ENCL_INFO_READ 0x271f
> +#define VPU_SW_RESET 0x2720
> +#define VPU_D2D3_MMC_CTRL 0x2721
> +#define VPU_CONT_MMC_CTRL 0x2722
> +#define VPU_CLK_GATE 0x2723
> +#define VPU_RDMA_MMC_CTRL 0x2724
> +#define VPU_MEM_PD_REG0 0x2725
> +#define VPU_MEM_PD_REG1 0x2726
> +#define VPU_HDMI_DATA_OVR 0x2727
> +#define VPU_PROT1_MMC_CTRL 0x2728
> +#define VPU_PROT2_MMC_CTRL 0x2729
> +#define VPU_PROT3_MMC_CTRL 0x272a
> +#define VPU_ARB4_V1_MMC_CTRL 0x272b
> +#define VPU_ARB4_V2_MMC_CTRL 0x272c
> +#define VPU_VPU_PWM_V0 0x2730
> +#define VPU_VPU_PWM_V1 0x2731
> +#define VPU_VPU_PWM_V2 0x2732
> +#define VPU_VPU_PWM_V3 0x2733
> +#define VPU_VPU_PWM_H0 0x2734
> +#define VPU_VPU_PWM_H1 0x2735
> +#define VPU_VPU_PWM_H2 0x2736
> +#define VPU_VPU_PWM_H3 0x2737
> +#define VPU_MISC_CTRL 0x2740
> +#define VPU_ISP_GCLK_CTRL0 0x2741
> +#define VPU_ISP_GCLK_CTRL1 0x2742
> +#define VPU_VDIN_ASYNC_HOLD_CTRL 0x2743
> +#define VPU_VDISP_ASYNC_HOLD_CTRL 0x2744
> +#define VPU_VPUARB2_ASYNC_HOLD_CTRL 0x2745
> +
> +#define VPU_PROT1_CLK_GATE 0x2750
> +#define VPU_PROT1_GEN_CNTL 0x2751
> +#define VPU_PROT1_X_START_END 0x2752
> +#define VPU_PROT1_Y_START_END 0x2753
> +#define VPU_PROT1_Y_LEN_STEP 0x2754
> +#define VPU_PROT1_RPT_LOOP 0x2755
> +#define VPU_PROT1_RPT_PAT 0x2756
> +#define VPU_PROT1_DDR 0x2757
> +#define VPU_PROT1_RBUF_ROOM 0x2758
> +#define VPU_PROT1_STAT_0 0x2759
> +#define VPU_PROT1_STAT_1 0x275a
> +#define VPU_PROT1_STAT_2 0x275b
> +#define VPU_PROT1_REQ_ONOFF 0x275c
> +#define VPU_PROT2_CLK_GATE 0x2760
> +#define VPU_PROT2_GEN_CNTL 0x2761
> +#define VPU_PROT2_X_START_END 0x2762
> +#define VPU_PROT2_Y_START_END 0x2763
> +#define VPU_PROT2_Y_LEN_STEP 0x2764
> +#define VPU_PROT2_RPT_LOOP 0x2765
> +#define VPU_PROT2_RPT_PAT 0x2766
> +#define VPU_PROT2_DDR 0x2767
> +#define VPU_PROT2_RBUF_ROOM 0x2768
> +#define VPU_PROT2_STAT_0 0x2769
> +#define VPU_PROT2_STAT_1 0x276a
> +#define VPU_PROT2_STAT_2 0x276b
> +#define VPU_PROT2_REQ_ONOFF 0x276c
> +#define VPU_PROT3_CLK_GATE 0x2770
> +#define VPU_PROT3_GEN_CNTL 0x2771
> +#define VPU_PROT3_X_START_END 0x2772
> +#define VPU_PROT3_Y_START_END 0x2773
> +#define VPU_PROT3_Y_LEN_STEP 0x2774
> +#define VPU_PROT3_RPT_LOOP 0x2775
> +#define VPU_PROT3_RPT_PAT 0x2776
> +#define VPU_PROT3_DDR 0x2777
> +#define VPU_PROT3_RBUF_ROOM 0x2778
> +#define VPU_PROT3_STAT_0 0x2779
> +#define VPU_PROT3_STAT_1 0x277a
> +#define VPU_PROT3_STAT_2 0x277b
> +#define VPU_PROT3_REQ_ONOFF 0x277c
> +
> +/* osd super scale */
> +#define OSDSR_HV_SIZEIN 0x3130
> +#define OSDSR_CTRL_MODE 0x3131
> +#define OSDSR_ABIC_HCOEF 0x3132
> +#define OSDSR_YBIC_HCOEF 0x3133
> +#define OSDSR_CBIC_HCOEF 0x3134
> +#define OSDSR_ABIC_VCOEF 0x3135
> +#define OSDSR_YBIC_VCOEF 0x3136
> +#define OSDSR_CBIC_VCOEF 0x3137
> +#define OSDSR_VAR_PARA 0x3138
> +#define OSDSR_CONST_PARA 0x3139
> +#define OSDSR_RKE_EXTWIN 0x313a
> +#define OSDSR_UK_GRAD2DDIAG_TH_RATE 0x313b
> +#define OSDSR_UK_GRAD2DDIAG_LIMIT 0x313c
> +#define OSDSR_UK_GRAD2DADJA_TH_RATE 0x313d
> +#define OSDSR_UK_GRAD2DADJA_LIMIT 0x313e
> +#define OSDSR_UK_BST_GAIN 0x313f
> +#define OSDSR_HVBLEND_TH 0x3140
> +#define OSDSR_DEMO_WIND_TB 0x3141
> +#define OSDSR_DEMO_WIND_LR 0x3142
> +#define OSDSR_INT_BLANK_NUM 0x3143
> +#define OSDSR_FRM_END_STAT 0x3144
> +#define OSDSR_ABIC_HCOEF0 0x3145
> +#define OSDSR_YBIC_HCOEF0 0x3146
> +#define OSDSR_CBIC_HCOEF0 0x3147
> +#define OSDSR_ABIC_VCOEF0 0x3148
> +#define OSDSR_YBIC_VCOEF0 0x3149
> +#define OSDSR_CBIC_VCOEF0 0x314a
> +
> +#endif /* __MESON_REGISTERS_H */
> diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c
> new file mode 100644
> index 0000000..c8c575d
> --- /dev/null
> +++ b/drivers/gpu/drm/meson/meson_vclk.c
> @@ -0,0 +1,169 @@
> +/*
> + * Copyright (C) 2016 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong@xxxxxxxxxxxx>
> + * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
> + * 02111-1307, USA.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <drm/drmP.h>
> +#include "meson_drv.h"
> +#include "meson_vclk.h"
> +
> +/*
> + * VCLK is the "Pixel Clock" frequency generator from a dedicated PLL.
> + * We handle the following encodings :
> + * - CVBS 27MHz generator via the VCLK2 to the VENCI and VDAC blocks
> + *
> + * What is missing :
> + * - HDMI Pixel Clocks generation
> + */
> +
> +/* HHI Registers */
> +#define HHI_VID_PLL_CLK_DIV 0x1a0 /* 0x68 offset in data sheet */
> +#define VID_PLL_EN BIT(19)
> +#define VID_PLL_BYPASS BIT(18)
> +#define VID_PLL_PRESET BIT(15)
> +#define HHI_VIID_CLK_DIV 0x128 /* 0x4a offset in data sheet */
> +#define VCLK2_DIV_MASK 0xff
> +#define VCLK2_DIV_EN BIT(16)
> +#define VCLK2_DIV_RESET BIT(17)
> +#define CTS_VDAC_SEL_MASK (0xf << 28)
> +#define CTS_VDAC_SEL_SHIFT 28
> +#define HHI_VIID_CLK_CNTL 0x12c /* 0x4b offset in data sheet */
> +#define VCLK2_EN BIT(19)
> +#define VCLK2_SEL_MASK (0x7 << 16)
> +#define VCLK2_SEL_SHIFT 16
> +#define VCLK2_SOFT_RESET BIT(15)
> +#define VCLK2_DIV1_EN BIT(0)
> +#define HHI_VID_CLK_DIV 0x164 /* 0x59 offset in data sheet */
> +#define CTS_ENCI_SEL_MASK (0xf << 28)
> +#define CTS_ENCI_SEL_SHIFT 28
> +#define HHI_VID_CLK_CNTL2 0x194 /* 0x65 offset in data sheet */
> +#define CTS_ENCI_EN BIT(0)
> +#define CTS_VDAC_EN BIT(4)
> +
> +#define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */
> +#define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */
> +
> +#define HHI_HDMI_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */
> +#define HHI_HDMI_PLL_CNTL2 0x324 /* 0xc9 offset in data sheet */
> +#define HHI_HDMI_PLL_CNTL3 0x328 /* 0xca offset in data sheet */
> +#define HHI_HDMI_PLL_CNTL4 0x32C /* 0xcb offset in data sheet */
> +#define HHI_HDMI_PLL_CNTL5 0x330 /* 0xcc offset in data sheet */
> +#define HHI_HDMI_PLL_CNTL6 0x334 /* 0xcd offset in data sheet */
> +
> +#define HDMI_PLL_RESET BIT(28)
> +#define HDMI_PLL_LOCK BIT(31)
> +
> +/*
> + * Setup VCLK2 for 27MHz, and enable clocks for ENCI and VDAC
> + *
> + * TOFIX: Refactor into table to also handle HDMI frequency and paths
> + */
> +static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
> +{
> + unsigned int val;
> +
> + /* Setup PLL to output 1.485GHz */
> + if (of_machine_is_compatible("amlogic,meson-gxbb")) {
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800023d);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00404e00);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4800023d);
> + } else if (of_machine_is_compatible("amlogic,meson-gxm") ||
> + of_machine_is_compatible("amlogic,meson-gxl")) {
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4000027b);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb300);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0xa6212844);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c4d000c);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
> +
> + /* Reset PLL */
> + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
> + HDMI_PLL_RESET, HDMI_PLL_RESET);
> + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
> + HDMI_PLL_RESET, 0);
> + }
> +
> + /* Poll for lock bit */
> + regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
> + (val & HDMI_PLL_LOCK), 10, 0);
> +
> + /* Disable VCLK2 */
> + regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, 0);
> +
> + /* Disable vid_pll output clock */
> + regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_EN, 0);
> + regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_PRESET, 0);
> + /* Enable vid_pll bypass to HDMI pll */
> + regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
> + VID_PLL_BYPASS, VID_PLL_BYPASS);
> + /* Enable the vid_pll output clock */
> + regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
> + VID_PLL_EN, VID_PLL_EN);
> +
> + /* Setup the VCLK2 divider value to achieve 27MHz */
> + regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
> + VCLK2_DIV_MASK, (55 - 1));
> +
> + /* select vid_pll for vclk2 */
> + regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
> + VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
> + /* enable vclk2 gate */
> + regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, VCLK2_EN);
> +
> + /* select vclk_div1 for enci */
> + regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
> + CTS_ENCI_SEL_MASK, (8 << CTS_ENCI_SEL_SHIFT));
> + /* select vclk_div1 for vdac */
> + regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
> + CTS_VDAC_SEL_MASK, (8 << CTS_VDAC_SEL_SHIFT));
> +
> + /* release vclk2_div_reset and enable vclk2_div */
> + regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
> + VCLK2_DIV_EN | VCLK2_DIV_RESET, VCLK2_DIV_EN);
> +
> + /* enable vclk2_div1 gate */
> + regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
> + VCLK2_DIV1_EN, VCLK2_DIV1_EN);
> +
> + /* reset vclk2 */
> + regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
> + VCLK2_SOFT_RESET, VCLK2_SOFT_RESET);
> + regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
> + VCLK2_SOFT_RESET, 0);
> +
> + /* enable enci_clk */
> + regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
> + CTS_ENCI_EN, CTS_ENCI_EN);
> + /* enable vdac_clk */
> + regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
> + CTS_VDAC_EN, CTS_VDAC_EN);
> +}
> +
> +void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
> + unsigned int freq)
> +{
> + if (target == MESON_VCLK_TARGET_CVBS && freq == MESON_VCLK_CVBS)
> + meson_venci_cvbs_clock_config(priv);
> +}
> diff --git a/drivers/gpu/drm/meson/meson_vclk.h b/drivers/gpu/drm/meson/meson_vclk.h
> new file mode 100644
> index 0000000..444d6a4
> --- /dev/null
> +++ b/drivers/gpu/drm/meson/meson_vclk.h
> @@ -0,0 +1,36 @@
> +/*
> + * Copyright (C) 2016 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong@xxxxxxxxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
> + * 02111-1307, USA.
> + */
> +
> +/* Video Clock */
> +
> +#ifndef __MESON_VCLK_H
> +#define __MESON_VCLK_H
> +
> +enum {
> + MESON_VCLK_TARGET_CVBS = 0,
> +};
> +
> +/* 27MHz is the CVBS Pixel Clock */
> +#define MESON_VCLK_CVBS 27000
> +
> +void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
> + unsigned int freq);
> +
> +#endif /* __MESON_VCLK_H */
> diff --git a/drivers/gpu/drm/meson/meson_venc.c b/drivers/gpu/drm/meson/meson_venc.c
> new file mode 100644
> index 0000000..c2a08df
> --- /dev/null
> +++ b/drivers/gpu/drm/meson/meson_venc.c
> @@ -0,0 +1,286 @@
> +/*
> + * Copyright (C) 2016 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong@xxxxxxxxxxxx>
> + * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
> + * 02111-1307, USA.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <drm/drmP.h>
> +#include "meson_drv.h"
> +#include "meson_venc.h"
> +#include "meson_vpp.h"
> +#include "meson_vclk.h"
> +#include "meson_registers.h"
> +
> +/*
> + * VENC Handle the pixels encoding to the output formats.
> + * We handle the following encodings :
> + * - CVBS Encoding via the ENCI encoder and VDAC digital to analog converter
> + *
> + * What is missing :
> + * - TMDS/HDMI Encoding via ENCI_DIV and ENCP
> + * - Setup of more clock rates for HDMI modes
> + * - LCD Panel encoding via ENCL
> + * - TV Panel encoding via ENCT
> + */
> +
> +/* HHI Registers */
> +#define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */
> +#define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */
> +
> +struct meson_cvbs_enci_mode meson_cvbs_enci_pal = {
> + .mode_tag = MESON_VENC_MODE_CVBS_PAL,
> + .hso_begin = 3,
> + .hso_end = 129,
> + .vso_even = 3,
> + .vso_odd = 260,
> + .macv_max_amp = 7,
> + .video_prog_mode = 0xff,
> + .video_mode = 0x13,
> + .sch_adjust = 0x28,
> + .yc_delay = 0x343,
> + .pixel_start = 251,
> + .pixel_end = 1691,
> + .top_field_line_start = 22,
> + .top_field_line_end = 310,
> + .bottom_field_line_start = 23,
> + .bottom_field_line_end = 311,
> + .video_saturation = 9,
> + .video_contrast = 0,
> + .video_brightness = 0,
> + .video_hue = 0,
> + .analog_sync_adj = 0x8080,
> +};
> +
> +struct meson_cvbs_enci_mode meson_cvbs_enci_ntsc = {
> + .mode_tag = MESON_VENC_MODE_CVBS_NTSC,
> + .hso_begin = 5,
> + .hso_end = 129,
> + .vso_even = 3,
> + .vso_odd = 260,
> + .macv_max_amp = 0xb,
> + .video_prog_mode = 0xf0,
> + .video_mode = 0x8,
> + .sch_adjust = 0x20,
> + .yc_delay = 0x333,
> + .pixel_start = 227,
> + .pixel_end = 1667,
> + .top_field_line_start = 18,
> + .top_field_line_end = 258,
> + .bottom_field_line_start = 19,
> + .bottom_field_line_end = 259,
> + .video_saturation = 18,
> + .video_contrast = 3,
> + .video_brightness = 0,
> + .video_hue = 0,
> + .analog_sync_adj = 0x9c00,
> +};
> +
> +void meson_venci_cvbs_mode_set(struct meson_drm *priv,
> + struct meson_cvbs_enci_mode *mode)
> +{
> + if (mode->mode_tag == priv->venc.current_mode)
> + return;
> +
> + /* CVBS Filter settings */
> + writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL));
> + writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2));
> +
> + /* Digital Video Select : Interlace, clk27 clk, external */
> + writel_relaxed(0, priv->io_base + _REG(VENC_DVI_SETTING));
> +
> + /* Reset Video Mode */
> + writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE));
> + writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
> +
> + /* Horizontal sync signal output */
> + writel_relaxed(mode->hso_begin,
> + priv->io_base + _REG(ENCI_SYNC_HSO_BEGIN));
> + writel_relaxed(mode->hso_end,
> + priv->io_base + _REG(ENCI_SYNC_HSO_END));
> +
> + /* Vertical Sync lines */
> + writel_relaxed(mode->vso_even,
> + priv->io_base + _REG(ENCI_SYNC_VSO_EVNLN));
> + writel_relaxed(mode->vso_odd,
> + priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));
> +
> + /* Macrovision max amplitude change */
> + writel_relaxed(0x8100 + mode->macv_max_amp,
> + priv->io_base + _REG(ENCI_MACV_MAX_AMP));
> +
> + /* Video mode */
> + writel_relaxed(mode->video_prog_mode,
> + priv->io_base + _REG(VENC_VIDEO_PROG_MODE));
> + writel_relaxed(mode->video_mode,
> + priv->io_base + _REG(ENCI_VIDEO_MODE));
> +
> + /* Advanced Video Mode :
> + * Demux shifting 0x2
> + * Blank line end at line17/22
> + * High bandwidth Luma Filter
> + * Low bandwidth Chroma Filter
> + * Bypass luma low pass filter
> + * No macrovision on CSYNC
> + */
> + writel_relaxed(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
> +
> + writel(mode->sch_adjust, priv->io_base + _REG(ENCI_VIDEO_SCH));
> +
> + /* Sync mode : MASTER Master mode, free run, send HSO/VSO out */
> + writel_relaxed(0x07, priv->io_base + _REG(ENCI_SYNC_MODE));
> +
> + /* 0x3 Y, C, and Component Y delay */
> + writel_relaxed(mode->yc_delay, priv->io_base + _REG(ENCI_YC_DELAY));
> +
> + /* Timings */
> + writel_relaxed(mode->pixel_start,
> + priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_START));
> + writel_relaxed(mode->pixel_end,
> + priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_END));
> +
> + writel_relaxed(mode->top_field_line_start,
> + priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_START));
> + writel_relaxed(mode->top_field_line_end,
> + priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_END));
> +
> + writel_relaxed(mode->bottom_field_line_start,
> + priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_START));
> + writel_relaxed(mode->bottom_field_line_end,
> + priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_END));
> +
> + /* Internal Venc, Internal VIU Sync, Internal Vencoder */
> + writel_relaxed(0, priv->io_base + _REG(VENC_SYNC_ROUTE));
> +
> + /* UNreset Interlaced TV Encoder */
> + writel_relaxed(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
> +
> + /* Enable Vfifo2vd, Y_Cb_Y_Cr select */
> + writel_relaxed(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
> +
> + /* Power UP Dacs */
> + writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_SETTING));
> +
> + /* Video Upsampling */
> + writel_relaxed(0x0061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL0));
> + writel_relaxed(0x4061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL1));
> + writel_relaxed(0x5061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL2));
> +
> + /* Select Interlace Y DACs */
> + writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
> + writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL1));
> + writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL2));
> + writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL3));
> + writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL4));
> + writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL5));
> +
> + /* Select ENCI for VIU */
> + meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
> +
> + /* Enable ENCI FIFO */
> + writel_relaxed(0x2000, priv->io_base + _REG(VENC_VDAC_FIFO_CTRL));
> +
> + /* Select ENCI DACs 0, 1, 4, and 5 */
> + writel_relaxed(0x11, priv->io_base + _REG(ENCI_DACSEL_0));
> + writel_relaxed(0x11, priv->io_base + _REG(ENCI_DACSEL_1));
> +
> + /* Interlace video enable */
> + writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
> +
> + /* Configure Video Saturation / Contrast / Brightness / Hue */
> + writel_relaxed(mode->video_saturation,
> + priv->io_base + _REG(ENCI_VIDEO_SAT));
> + writel_relaxed(mode->video_contrast,
> + priv->io_base + _REG(ENCI_VIDEO_CONT));
> + writel_relaxed(mode->video_brightness,
> + priv->io_base + _REG(ENCI_VIDEO_BRIGHT));
> + writel_relaxed(mode->video_hue,
> + priv->io_base + _REG(ENCI_VIDEO_HUE));
> +
> + /* Enable DAC0 Filter */
> + writel_relaxed(0x1, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL0));
> + writel_relaxed(0xfc48, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL1));
> +
> + /* 0 in Macrovision register 0 */
> + writel_relaxed(0, priv->io_base + _REG(ENCI_MACV_N0));
> +
> + /* Analog Synchronization and color burst value adjust */
> + writel_relaxed(mode->analog_sync_adj,
> + priv->io_base + _REG(ENCI_SYNC_ADJ));
> +
> + /* Setup 27MHz vclk2 for ENCI and VDAC */
> + meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS, MESON_VCLK_CVBS);
> +
> + priv->venc.current_mode = mode->mode_tag;
> +}
> +
> +void meson_venci_cvbs_enable(struct meson_drm *priv)
> +{
> + /* VDAC0 source is not from ATV */
> + writel_bits_relaxed(BIT(5), 0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
> +
> + if (of_machine_is_compatible("amlogic,meson-gxbb"))
> + regmap_write(priv->hhi, HHI_VDAC_CNTL0, 1);
> + else if (of_machine_is_compatible("amlogic,meson-gxm") ||
> + of_machine_is_compatible("amlogic,meson-gxl"))
> + regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0xf0001);
> +
> + regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0);
> +
> + priv->venc.cvbs_enabled = true;
> +}
> +
> +void meson_venci_cvbs_disable(struct meson_drm *priv)
> +{
> + regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
> + regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0);
> +
> + priv->venc.cvbs_enabled = false;
> +}
> +
> +/* Returns the current ENCI field polarity */
> +unsigned int meson_venci_get_field(struct meson_drm *priv)
> +{
> + return readl_relaxed(priv->io_base + _REG(ENCI_INFO_READ)) & BIT(29);
> +}
> +
> +void meson_venc_enable_vsync(struct meson_drm *priv)
> +{
> + writel_relaxed(2, priv->io_base + _REG(VENC_INTCTRL));
> +}
> +
> +void meson_venc_disable_vsync(struct meson_drm *priv)
> +{
> + writel_relaxed(0, priv->io_base + _REG(VENC_INTCTRL));
> +}
> +
> +void meson_venc_init(struct meson_drm *priv)
> +{
> + /* Disable all encoders */
> + writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
> + writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
> + writel_relaxed(0, priv->io_base + _REG(ENCL_VIDEO_EN));
> +
> + /* Disable VSync IRQ */
> + meson_venc_disable_vsync(priv);
> +
> + meson_venci_cvbs_disable(priv);
> +
> + priv->venc.current_mode = MESON_VENC_MODE_NONE;
> +}
> diff --git a/drivers/gpu/drm/meson/meson_venc.h b/drivers/gpu/drm/meson/meson_venc.h
> new file mode 100644
> index 0000000..75a101b
> --- /dev/null
> +++ b/drivers/gpu/drm/meson/meson_venc.h
> @@ -0,0 +1,77 @@
> +/*
> + * Copyright (C) 2016 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong@xxxxxxxxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
> + * 02111-1307, USA.
> + */
> +
> +/*
> + * Video Encoders
> + * - ENCI : Interlace Video Encoder
> + * - ENCI_DVI : Interlace Video Encoder for DVI/HDMI
> + * - ENCP : Progressive Video Encoder
> + */
> +
> +#ifndef __MESON_VENC_H
> +#define __MESON_VENC_H
> +
> +enum {
> + MESON_VENC_MODE_NONE = 0,
> + MESON_VENC_MODE_CVBS_PAL,
> + MESON_VENC_MODE_CVBS_NTSC,
> +};
> +
> +struct meson_cvbs_enci_mode {
> + unsigned int mode_tag;
> + unsigned int hso_begin; /* HSO begin position */
> + unsigned int hso_end; /* HSO end position */
> + unsigned int vso_even; /* VSO even line */
> + unsigned int vso_odd; /* VSO odd line */
> + unsigned int macv_max_amp; /* Macrovision max amplitude */
> + unsigned int video_prog_mode;
> + unsigned int video_mode;
> + unsigned int sch_adjust;
> + unsigned int yc_delay;
> + unsigned int pixel_start;
> + unsigned int pixel_end;
> + unsigned int top_field_line_start;
> + unsigned int top_field_line_end;
> + unsigned int bottom_field_line_start;
> + unsigned int bottom_field_line_end;
> + unsigned int video_saturation;
> + unsigned int video_contrast;
> + unsigned int video_brightness;
> + unsigned int video_hue;
> + unsigned int analog_sync_adj;
> +};
> +
> +/* CVBS Timings and Parameters */
> +extern struct meson_cvbs_enci_mode meson_cvbs_enci_pal;
> +extern struct meson_cvbs_enci_mode meson_cvbs_enci_ntsc;
> +
> +void meson_venci_cvbs_mode_set(struct meson_drm *priv,
> + struct meson_cvbs_enci_mode *mode);
> +void meson_venci_cvbs_enable(struct meson_drm *priv);
> +void meson_venci_cvbs_disable(struct meson_drm *priv);
> +
> +unsigned int meson_venci_get_field(struct meson_drm *priv);
> +
> +void meson_venc_enable_vsync(struct meson_drm *priv);
> +void meson_venc_disable_vsync(struct meson_drm *priv);
> +
> +void meson_venc_init(struct meson_drm *priv);
> +
> +#endif /* __MESON_VENC_H */
> diff --git a/drivers/gpu/drm/meson/meson_viu.c b/drivers/gpu/drm/meson/meson_viu.c
> new file mode 100644
> index 0000000..66f251fb
> --- /dev/null
> +++ b/drivers/gpu/drm/meson/meson_viu.c
> @@ -0,0 +1,497 @@
> +/*
> + * Copyright (C) 2016 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong@xxxxxxxxxxxx>
> + * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
> + * Copyright (C) 2014 Endless Mobile
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
> + * 02111-1307, USA.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <drm/drmP.h>
> +#include "meson_drv.h"
> +#include "meson_viu.h"
> +#include "meson_vpp.h"
> +#include "meson_venc.h"
> +#include "meson_canvas.h"
> +#include "meson_registers.h"
> +
> +/*
> + * VIU Handles the Pixel scanout and the basic Colorspace conversions
> + * We handle the following features :
> + * - OSD1 RGB565/RGB888/xRGB8888 scanout
> + * - RGB conversion to x/cb/cr
> + * - Progressive or Interlace buffer scanout
> + * - OSD1 Commit on Vsync
> + * - HDR OSD matrix for GXL/GXM
> + *
> + * What is missing :
> + * - BGR888/xBGR8888/BGRx8888/BGRx8888 modes
> + * - YUV4:2:2 Y0CbY1Cr scanout
> + * - Conversion to YUV 4:4:4 from 4:2:2 input
> + * - Colorkey Alpha matching
> + * - Big endian scanout
> + * - X/Y reverse scanout
> + * - Global alpha setup
> + * - OSD2 support, would need interlace switching on vsync
> + * - OSD1 full scaling to support TV overscan
> + */
> +
> +/* OSDx_BLKx_CFG */
> +#define OSD_CANVAS_SEL 16
> +
> +#define OSD_ENDIANNESS_LE BIT(15)
> +#define OSD_ENDIANNESS_BE (0)
> +
> +#define OSD_BLK_MODE_422 (0x03 << 8)
> +#define OSD_BLK_MODE_16 (0x04 << 8)
> +#define OSD_BLK_MODE_32 (0x05 << 8)
> +#define OSD_BLK_MODE_24 (0x07 << 8)
> +
> +#define OSD_OUTPUT_COLOR_RGB BIT(7)
> +#define OSD_OUTPUT_COLOR_YUV (0)
> +
> +#define OSD_COLOR_MATRIX_32_RGBA (0x00 << 2)
> +#define OSD_COLOR_MATRIX_32_ARGB (0x01 << 2)
> +#define OSD_COLOR_MATRIX_32_ABGR (0x02 << 2)
> +#define OSD_COLOR_MATRIX_32_BGRA (0x03 << 2)
> +
> +#define OSD_COLOR_MATRIX_24_RGB (0x00 << 2)
> +
> +#define OSD_COLOR_MATRIX_16_RGB655 (0x00 << 2)
> +#define OSD_COLOR_MATRIX_16_RGB565 (0x04 << 2)
> +
> +#define OSD_INTERLACE_ENABLED BIT(1)
> +#define OSD_INTERLACE_ODD BIT(0)
> +#define OSD_INTERLACE_EVEN (0)
> +
> +/* OSDx_CTRL_STAT */
> +#define OSD_ENABLE BIT(21)
> +#define OSD_BLK0_ENABLE BIT(0)
> +
> +#define OSD_GLOBAL_ALPHA_SHIFT 12
> +
> +/* OSDx_CTRL_STAT2 */
> +#define OSD_REPLACE_EN BIT(14)
> +#define OSD_REPLACE_SHIFT 6
> +
> +/* Takes a fixed 16.16 number and converts it to integer. */
> +static inline int64_t fixed16_to_int(int64_t value)
> +{
> + return value >> 16;
> +}
> +
> +void meson_viu_update_osd1(struct meson_drm *priv, struct drm_plane *plane)
> +{
> + struct drm_plane_state *state = plane->state;
> + struct drm_framebuffer *fb = state->fb;
> + struct drm_rect src = {
> + .x1 = (state->src_x),
> + .y1 = (state->src_y),
> + .x2 = (state->src_x + state->src_w),
> + .y2 = (state->src_y + state->src_h),
> + };
> + struct drm_rect dest = {
> + .x1 = state->crtc_x,
> + .y1 = state->crtc_y,
> + .x2 = state->crtc_x + state->crtc_w,
> + .y2 = state->crtc_y + state->crtc_h,
> + };
> + unsigned long flags;
> +
> + spin_lock_irqsave(&priv->drm->event_lock, flags);
> +
> + /* Enable OSD and BLK0, set max global alpha */
> + priv->viu.osd1_ctrl_stat = OSD_ENABLE |
> + (0xFF << OSD_GLOBAL_ALPHA_SHIFT) |
> + OSD_BLK0_ENABLE;
> +
> + /* Set up BLK0 to point to the right canvas */
> + priv->viu.osd1_blk0_cfg[0] = ((MESON_CANVAS_ID_OSD1 << OSD_CANVAS_SEL) |
> + OSD_ENDIANNESS_LE);
> +
> + /* On GXBB, Use the old non-HDR RGB2YUV converter */
> + if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
> + priv->viu.osd1_blk0_cfg[0] |= OSD_OUTPUT_COLOR_RGB;
> +
> + switch (fb->pixel_format) {
> + case DRM_FORMAT_XRGB8888:
> + /* For XRGB, replace the pixel's alpha by 0xFF */
> + writel_bits_relaxed(OSD_REPLACE_EN, OSD_REPLACE_EN,
> + priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
> + priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_32 |
> + OSD_COLOR_MATRIX_32_ARGB;
> + break;
> + case DRM_FORMAT_ARGB8888:
> + /* For ARGB, use the pixel's alpha */
> + writel_bits_relaxed(OSD_REPLACE_EN, 0,
> + priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
> + priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_32 |
> + OSD_COLOR_MATRIX_32_ARGB;
> + break;
> + case DRM_FORMAT_RGB888:
> + priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_24 |
> + OSD_COLOR_MATRIX_24_RGB;
> + break;
> + case DRM_FORMAT_RGB565:
> + priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_16 |
> + OSD_COLOR_MATRIX_16_RGB565;
> + break;
> + };
> +
> + if (state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) {
> + priv->viu.osd1_interlace = true;
> +
> + dest.y1 /= 2;
> + dest.y2 /= 2;
> + } else {
> + priv->viu.osd1_interlace = true;
> + meson_vpp_disable_interlace_vscaler_osd1(priv);
> + }
> +
> + /*
> + * The format of these registers is (x2 << 16 | x1),
> + * where x2 is exclusive.
> + * e.g. +30x1920 would be (1919 << 16) | 30
> + */
> + priv->viu.osd1_blk0_cfg[1] = ((fixed16_to_int(src.x2) - 1) << 16) |
> + fixed16_to_int(src.x1);
> + priv->viu.osd1_blk0_cfg[2] = ((fixed16_to_int(src.y2) - 1) << 16) |
> + fixed16_to_int(src.y1);
> + priv->viu.osd1_blk0_cfg[3] = ((dest.x2 - 1) << 16) | dest.x1;
> + priv->viu.osd1_blk0_cfg[4] = ((dest.y2 - 1) << 16) | dest.y1;
> +
> + spin_unlock_irqrestore(&priv->drm->event_lock, flags);
> +}
> +
> +void meson_viu_sync_osd1(struct meson_drm *priv)
> +{
> + /* Update the OSD registers */
> + if (priv->viu.osd1_enabled && priv->viu.osd1_commit) {
> + writel_relaxed(priv->viu.osd1_ctrl_stat,
> + priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
> + writel_relaxed(priv->viu.osd1_blk0_cfg[0],
> + priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W0));
> + writel_relaxed(priv->viu.osd1_blk0_cfg[1],
> + priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W1));
> + writel_relaxed(priv->viu.osd1_blk0_cfg[2],
> + priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W2));
> + writel_relaxed(priv->viu.osd1_blk0_cfg[3],
> + priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W3));
> + writel_relaxed(priv->viu.osd1_blk0_cfg[4],
> + priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W4));
> +
> + if (priv->viu.osd1_interlace) {
> + struct drm_plane *plane = priv->primary_plane;
> + struct drm_plane_state *state = plane->state;
> + struct drm_rect dest = {
> + .x1 = state->crtc_x,
> + .y1 = state->crtc_y,
> + .x2 = state->crtc_x + state->crtc_w,
> + .y2 = state->crtc_y + state->crtc_h,
> + };
> +
> + meson_vpp_setup_interlace_vscaler_osd1(priv, &dest);
> + }
> +
> + meson_vpp_enable_osd1(priv);
> +
> + priv->viu.osd1_commit = false;
> + }
> +}

Again I'd remove the indirection and for these put them into your plane
implementation directly.

> +
> +
> +/* OSD csc defines */
> +
> +enum viu_matrix_sel_e {
> + VIU_MATRIX_OSD_EOTF = 0,
> + VIU_MATRIX_OSD,
> +};
> +
> +enum viu_lut_sel_e {
> + VIU_LUT_OSD_EOTF = 0,
> + VIU_LUT_OSD_OETF,
> +};
> +
> +#define COEFF_NORM(a) ((int)((((a) * 2048.0) + 1) / 2))
> +#define MATRIX_5X3_COEF_SIZE 24
> +
> +#define EOTF_COEFF_NORM(a) ((int)((((a) * 4096.0) + 1) / 2))
> +#define EOTF_COEFF_SIZE 10
> +#define EOTF_COEFF_RIGHTSHIFT 1
> +
> +static int RGB709_to_YUV709l_coeff[MATRIX_5X3_COEF_SIZE] = {
> + 0, 0, 0, /* pre offset */
> + COEFF_NORM(0.181873), COEFF_NORM(0.611831), COEFF_NORM(0.061765),
> + COEFF_NORM(-0.100251), COEFF_NORM(-0.337249), COEFF_NORM(0.437500),
> + COEFF_NORM(0.437500), COEFF_NORM(-0.397384), COEFF_NORM(-0.040116),
> + 0, 0, 0, /* 10'/11'/12' */
> + 0, 0, 0, /* 20'/21'/22' */
> + 64, 512, 512, /* offset */
> + 0, 0, 0 /* mode, right_shift, clip_en */
> +};
> +
> +/* eotf matrix: bypass */
> +static int eotf_bypass_coeff[EOTF_COEFF_SIZE] = {
> + EOTF_COEFF_NORM(1.0), EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(0.0),
> + EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(1.0), EOTF_COEFF_NORM(0.0),
> + EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(1.0),
> + EOTF_COEFF_RIGHTSHIFT /* right shift */
> +};
> +
> +void meson_viu_set_osd_matrix(struct meson_drm *priv,
> + enum viu_matrix_sel_e m_select,
> + int *m, bool csc_on)
> +{
> + if (m_select == VIU_MATRIX_OSD) {
> + /* osd matrix, VIU_MATRIX_0 */
> + writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
> + priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET0_1));
> + writel(m[2] & 0xfff,
> + priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET2));
> + writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
> + priv->io_base + _REG(VIU_OSD1_MATRIX_COEF00_01));
> + writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
> + priv->io_base + _REG(VIU_OSD1_MATRIX_COEF02_10));
> + writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
> + priv->io_base + _REG(VIU_OSD1_MATRIX_COEF11_12));
> + writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
> + priv->io_base + _REG(VIU_OSD1_MATRIX_COEF20_21));
> +
> + if (m[21]) {
> + writel(((m[11] & 0x1fff) << 16) | (m[12] & 0x1fff),
> + priv->io_base +
> + _REG(VIU_OSD1_MATRIX_COEF22_30));
> + writel(((m[13] & 0x1fff) << 16) | (m[14] & 0x1fff),
> + priv->io_base +
> + _REG(VIU_OSD1_MATRIX_COEF31_32));
> + writel(((m[15] & 0x1fff) << 16) | (m[16] & 0x1fff),
> + priv->io_base +
> + _REG(VIU_OSD1_MATRIX_COEF40_41));
> + writel(m[17] & 0x1fff, priv->io_base +
> + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
> + } else
> + writel((m[11] & 0x1fff) << 16, priv->io_base +
> + _REG(VIU_OSD1_MATRIX_COEF22_30));
> +
> + writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
> + priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET0_1));
> + writel(m[20] & 0xfff,
> + priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET2));
> +
> + writel_bits_relaxed(3 << 30, m[21] << 30,
> + priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
> + writel_bits_relaxed(7 << 16, m[22] << 16,
> + priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
> +
> + /* 23 reserved for clipping control */
> + writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
> + priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
> + writel_bits_relaxed(BIT(1), 0,
> + priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
> + } else if (m_select == VIU_MATRIX_OSD_EOTF) {
> + int i;
> +
> + /* osd eotf matrix, VIU_MATRIX_OSD_EOTF */
> + for (i = 0; i < 5; i++)
> + writel(((m[i * 2] & 0x1fff) << 16) |
> + (m[i * 2 + 1] & 0x1fff), priv->io_base +
> + _REG(VIU_OSD1_EOTF_CTL + i + 1));
> +
> + writel_bits_relaxed(BIT(30), csc_on ? BIT(30) : 0,
> + priv->io_base + _REG(VIU_OSD1_EOTF_CTL));
> + writel_bits_relaxed(BIT(31), csc_on ? BIT(31) : 0,
> + priv->io_base + _REG(VIU_OSD1_EOTF_CTL));
> + }
> +}
> +
> +#define OSD_EOTF_LUT_SIZE 33
> +#define OSD_OETF_LUT_SIZE 41
> +
> +void meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel,
> + unsigned int *r_map, unsigned int *g_map,
> + unsigned int *b_map,
> + bool csc_on)
> +{
> + unsigned int addr_port;
> + unsigned int data_port;
> + unsigned int ctrl_port;
> + int i;
> +
> + if (lut_sel == VIU_LUT_OSD_EOTF) {
> + addr_port = VIU_OSD1_EOTF_LUT_ADDR_PORT;
> + data_port = VIU_OSD1_EOTF_LUT_DATA_PORT;
> + ctrl_port = VIU_OSD1_EOTF_CTL;
> + } else if (lut_sel == VIU_LUT_OSD_OETF) {
> + addr_port = VIU_OSD1_OETF_LUT_ADDR_PORT;
> + data_port = VIU_OSD1_OETF_LUT_DATA_PORT;
> + ctrl_port = VIU_OSD1_OETF_CTL;
> + } else
> + return;
> +
> + if (lut_sel == VIU_LUT_OSD_OETF) {
> + writel(0, priv->io_base + _REG(addr_port));
> +
> + for (i = 0; i < 20; i++)
> + writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
> + priv->io_base + _REG(data_port));
> +
> + writel(r_map[OSD_OETF_LUT_SIZE - 1] | (g_map[0] << 16),
> + priv->io_base + _REG(data_port));
> +
> + for (i = 0; i < 20; i++)
> + writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
> + priv->io_base + _REG(data_port));
> +
> + for (i = 0; i < 20; i++)
> + writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
> + priv->io_base + _REG(data_port));
> +
> + writel(b_map[OSD_OETF_LUT_SIZE - 1],
> + priv->io_base + _REG(data_port));
> +
> + if (csc_on)
> + writel_bits_relaxed(0x7 << 29, 7 << 29,
> + priv->io_base + _REG(ctrl_port));
> + else
> + writel_bits_relaxed(0x7 << 29, 0,
> + priv->io_base + _REG(ctrl_port));
> + } else if (lut_sel == VIU_LUT_OSD_EOTF) {
> + writel(0, priv->io_base + _REG(addr_port));
> +
> + for (i = 0; i < 20; i++)
> + writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
> + priv->io_base + _REG(data_port));
> +
> + writel(r_map[OSD_EOTF_LUT_SIZE - 1] | (g_map[0] << 16),
> + priv->io_base + _REG(data_port));
> +
> + for (i = 0; i < 20; i++)
> + writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
> + priv->io_base + _REG(data_port));
> +
> + for (i = 0; i < 20; i++)
> + writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
> + priv->io_base + _REG(data_port));
> +
> + writel(b_map[OSD_EOTF_LUT_SIZE - 1],
> + priv->io_base + _REG(data_port));
> +
> + if (csc_on)
> + writel_bits_relaxed(7 << 27, 7 << 27,
> + priv->io_base + _REG(ctrl_port));
> + else
> + writel_bits_relaxed(7 << 27, 0,
> + priv->io_base + _REG(ctrl_port));
> +
> + writel_bits_relaxed(BIT(31), BIT(31),
> + priv->io_base + _REG(ctrl_port));
> + }
> +}
> +
> +/* eotf lut: linear */
> +static unsigned int eotf_33_linear_mapping[OSD_EOTF_LUT_SIZE] = {
> + 0x0000, 0x0200, 0x0400, 0x0600,
> + 0x0800, 0x0a00, 0x0c00, 0x0e00,
> + 0x1000, 0x1200, 0x1400, 0x1600,
> + 0x1800, 0x1a00, 0x1c00, 0x1e00,
> + 0x2000, 0x2200, 0x2400, 0x2600,
> + 0x2800, 0x2a00, 0x2c00, 0x2e00,
> + 0x3000, 0x3200, 0x3400, 0x3600,
> + 0x3800, 0x3a00, 0x3c00, 0x3e00,
> + 0x4000
> +};
> +
> +/* osd oetf lut: linear */
> +static unsigned int oetf_41_linear_mapping[OSD_OETF_LUT_SIZE] = {
> + 0, 0, 0, 0,
> + 0, 32, 64, 96,
> + 128, 160, 196, 224,
> + 256, 288, 320, 352,
> + 384, 416, 448, 480,
> + 512, 544, 576, 608,
> + 640, 672, 704, 736,
> + 768, 800, 832, 864,
> + 896, 928, 960, 992,
> + 1023, 1023, 1023, 1023,
> + 1023
> +};

Might be fun to expose this using the color manager stuff, see
drm_crtc_enable_color_mgmt().
> +
> +static void meson_viu_load_matrix(struct meson_drm *priv)
> +{
> + /* eotf lut bypass */
> + meson_viu_set_osd_lut(priv, VIU_LUT_OSD_EOTF,
> + eotf_33_linear_mapping, /* R */
> + eotf_33_linear_mapping, /* G */
> + eotf_33_linear_mapping, /* B */
> + false);
> +
> + /* eotf matrix bypass */
> + meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD_EOTF,
> + eotf_bypass_coeff,
> + false);
> +
> + /* oetf lut bypass */
> + meson_viu_set_osd_lut(priv, VIU_LUT_OSD_OETF,
> + oetf_41_linear_mapping, /* R */
> + oetf_41_linear_mapping, /* G */
> + oetf_41_linear_mapping, /* B */
> + false);
> +
> + /* osd matrix RGB709 to YUV709 limit */
> + meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD,
> + RGB709_to_YUV709l_coeff,
> + true);
> +}
> +
> +void meson_viu_init(struct meson_drm *priv)
> +{
> + uint32_t reg;
> +
> + /* Disable OSDs */
> + writel_bits_relaxed(BIT(0) | BIT(21), 0,
> + priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
> + writel_bits_relaxed(BIT(0) | BIT(21), 0,
> + priv->io_base + _REG(VIU_OSD2_CTRL_STAT));
> +
> + /* On GXL/GXM, Use the 10bit HDR conversion matrix */
> + if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
> + meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
> + meson_viu_load_matrix(priv);
> +
> + /* Initialize OSD1 fifo control register */
> + reg = BIT(0) | /* Urgent DDR request priority */
> + (4 << 5) | /* hold_fifo_lines */
> + (3 << 10) | /* burst length 64 */
> + (32 << 12) | /* fifo_depth_val: 32*8=256 */
> + (2 << 22) | /* 4 words in 1 burst */
> + (2 << 24);
> + writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
> + writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT));
> +
> + /* Set OSD alpha replace value */
> + writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT,
> + 0xff << OSD_REPLACE_SHIFT,
> + priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
> + writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT,
> + 0xff << OSD_REPLACE_SHIFT,
> + priv->io_base + _REG(VIU_OSD2_CTRL_STAT2));
> +
> + priv->viu.osd1_enabled = false;
> + priv->viu.osd1_commit = false;
> + priv->viu.osd1_interlace = false;
> +}
> diff --git a/drivers/gpu/drm/meson/meson_viu.h b/drivers/gpu/drm/meson/meson_viu.h
> new file mode 100644
> index 0000000..c7a7fb5
> --- /dev/null
> +++ b/drivers/gpu/drm/meson/meson_viu.h
> @@ -0,0 +1,37 @@
> +/*
> + * Copyright (C) 2016 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong@xxxxxxxxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
> + * 02111-1307, USA.
> + */
> +
> +/* Video Input Unit */
> +
> +#ifndef __MESON_VIU_H
> +#define __MESON_VIU_H
> +
> +/* Update OSD1 Coordinates */
> +void meson_viu_update_osd1(struct meson_drm *priv, struct drm_plane *plane);
> +
> +/* Commit OSD1 changes */
> +void meson_viu_commit_osd1(struct meson_drm *priv);
> +
> +/* Synchronize Field Change for OSD1 */
> +void meson_viu_sync_osd1(struct meson_drm *priv);
> +
> +void meson_viu_init(struct meson_drm *priv);
> +
> +#endif /* __MESON_VIU_H */
> diff --git a/drivers/gpu/drm/meson/meson_vpp.c b/drivers/gpu/drm/meson/meson_vpp.c
> new file mode 100644
> index 0000000..ea390d0
> --- /dev/null
> +++ b/drivers/gpu/drm/meson/meson_vpp.c
> @@ -0,0 +1,189 @@
> +/*
> + * Copyright (C) 2016 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong@xxxxxxxxxxxx>
> + * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
> + * Copyright (C) 2014 Endless Mobile
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
> + * 02111-1307, USA.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <drm/drmP.h>
> +#include "meson_drv.h"
> +#include "meson_vpp.h"
> +#include "meson_registers.h"
> +
> +/*
> + * VPP Handles all the Post Processing after the Scanout from the VIU
> + * We handle the following post processings :
> + * - Postblend : Blends the OSD1 only
> + * We exclude OSD2, VS1, VS1 and Preblend output
> + * - Vertical OSD Scaler for OSD1 only, we disable vertical scaler and
> + * use it only for interlace scanout
> + * - Intermediate FIFO with default Amlogic values
> + *
> + * What is missing :
> + * - Preblend for video overlay pre-scaling
> + * - OSD2 support for cursor framebuffer
> + * - Video pre-scaling before postblend
> + * - Full Vertical/Horizontal OSD scaling to support TV overscan
> + * - HDR conversion
> + */
> +
> +void meson_vpp_enable_osd1(struct meson_drm *priv)
> +{
> + writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
> + priv->io_base + _REG(VPP_MISC));
> +}
> +
> +void meson_vpp_disable_osd1(struct meson_drm *priv)
> +{
> + writel_bits_relaxed(VPP_OSD1_POSTBLEND, 0,
> + priv->io_base + _REG(VPP_MISC));
> +}
> +
> +void meson_vpp_enable_postblend(struct meson_drm *priv, unsigned int width)
> +{
> + writel(width, priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
> +
> + writel_bits_relaxed(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE,
> + priv->io_base + _REG(VPP_MISC));
> +}
> +
> +void meson_vpp_disable_postblend(struct meson_drm *priv)
> +{
> + writel_bits_relaxed(VPP_POSTBLEND_ENABLE, 0,
> + priv->io_base + _REG(VPP_MISC));
> +}
> +
> +void meson_vpp_setup_mux(struct meson_drm *priv, unsigned int mux)
> +{
> + writel(mux, priv->io_base + _REG(VPU_VIU_VENC_MUX_CTRL));
> +}
> +
> +/*
> + * When the output is interlaced, the OSD must switch between
> + * each field using the INTERLACE_SEL_ODD (0) of VIU_OSD1_BLK0_CFG_W0
> + * at each vsync.
> + * But the vertical scaler can provide such funtionnality if
> + * is configured for 2:1 scaling with interlace options enabled.
> + */
> +void meson_vpp_setup_interlace_vscaler_osd1(struct meson_drm *priv,
> + struct drm_rect *input)
> +{
> + writel_relaxed(BIT(3) /* Enable scaler */ |
> + BIT(2), /* Select OSD1 */
> + priv->io_base + _REG(VPP_OSD_SC_CTRL0));
> +
> + writel_relaxed(((drm_rect_width(input) - 1) << 16) |
> + (drm_rect_height(input) - 1),
> + priv->io_base + _REG(VPP_OSD_SCI_WH_M1));
> + /* 2:1 scaling */
> + writel_relaxed(((input->x1) << 16) | (input->x2),
> + priv->io_base + _REG(VPP_OSD_SCO_H_START_END));
> + writel_relaxed(((input->y1 >> 1) << 16) | (input->y2 >> 1),
> + priv->io_base + _REG(VPP_OSD_SCO_V_START_END));
> +
> + /* 2:1 scaling values */
> + writel_relaxed(BIT(16), priv->io_base + _REG(VPP_OSD_VSC_INI_PHASE));
> + writel_relaxed(BIT(25), priv->io_base + _REG(VPP_OSD_VSC_PHASE_STEP));
> +
> + writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
> +
> + writel_relaxed((4 << 0) /* osd_vsc_bank_length */ |
> + (4 << 3) /* osd_vsc_top_ini_rcv_num0 */ |
> + (1 << 8) /* osd_vsc_top_rpt_p0_num0 */ |
> + (6 << 11) /* osd_vsc_bot_ini_rcv_num0 */ |
> + (2 << 16) /* osd_vsc_bot_rpt_p0_num0 */ |
> + BIT(23) /* osd_prog_interlace */ |
> + BIT(24), /* Enable vertical scaler */
> + priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
> +}
> +
> +void meson_vpp_disable_interlace_vscaler_osd1(struct meson_drm *priv)
> +{
> + writel_relaxed(0, priv->io_base + _REG(VPP_OSD_SC_CTRL0));
> + writel_relaxed(0, priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
> + writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
> +}
> +
> +static unsigned int vpp_filter_coefs_4point_bspline[] = {
> + 0x15561500, 0x14561600, 0x13561700, 0x12561800,
> + 0x11551a00, 0x11541b00, 0x10541c00, 0x0f541d00,
> + 0x0f531e00, 0x0e531f00, 0x0d522100, 0x0c522200,
> + 0x0b522300, 0x0b512400, 0x0a502600, 0x0a4f2700,
> + 0x094e2900, 0x084e2a00, 0x084d2b00, 0x074c2c01,
> + 0x074b2d01, 0x064a2f01, 0x06493001, 0x05483201,
> + 0x05473301, 0x05463401, 0x04453601, 0x04433702,
> + 0x04423802, 0x03413a02, 0x03403b02, 0x033f3c02,
> + 0x033d3d03
> +};
> +
> +static void meson_vpp_write_scaling_filter_coefs(struct meson_drm *priv,
> + const unsigned int *coefs,
> + bool is_horizontal)
> +{
> + int i;
> +
> + writel_relaxed(is_horizontal ? BIT(8) : 0,
> + priv->io_base + _REG(VPP_OSD_SCALE_COEF_IDX));
> + for (i = 0; i < 33; i++)
> + writel_relaxed(coefs[i],
> + priv->io_base + _REG(VPP_OSD_SCALE_COEF));
> +}
> +
> +void meson_vpp_init(struct meson_drm *priv)
> +{
> + /* set dummy data default YUV black */
> + if (meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
> + writel_relaxed(0x108080, priv->io_base + _REG(VPP_DUMMY_DATA1));
> + else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu")) {
> + writel_bits_relaxed(0xff << 16, 0xff << 16,
> + priv->io_base + _REG(VIU_MISC_CTRL1));
> + writel_relaxed(0x20000, priv->io_base + _REG(VPP_DOLBY_CTRL));
> + writel_relaxed(0x1020080,
> + priv->io_base + _REG(VPP_DUMMY_DATA1));
> + }
> +
> + /* Initialize vpu fifo control registers */
> + writel_relaxed(readl_relaxed(priv->io_base + _REG(VPP_OFIFO_SIZE)) |
> + 0x77f, priv->io_base + _REG(VPP_OFIFO_SIZE));
> + writel_relaxed(0x08080808, priv->io_base + _REG(VPP_HOLD_LINES));
> +
> + /* Turn off preblend */
> + writel_bits_relaxed(VPP_PREBLEND_ENABLE, 0,
> + priv->io_base + _REG(VPP_MISC));
> +
> + /* Turn off POSTBLEND */
> + meson_vpp_disable_postblend(priv);
> +
> + /* Force all planes off */
> + writel_bits_relaxed(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND |
> + VPP_VD1_POSTBLEND | VPP_VD2_POSTBLEND, 0,
> + priv->io_base + _REG(VPP_MISC));
> +
> + /* Disable Scalers */
> + writel_relaxed(0, priv->io_base + _REG(VPP_OSD_SC_CTRL0));
> + writel_relaxed(0, priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
> + writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
> +
> + /* Write in the proper filter coefficients. */
> + meson_vpp_write_scaling_filter_coefs(priv,
> + vpp_filter_coefs_4point_bspline, false);
> + meson_vpp_write_scaling_filter_coefs(priv,
> + vpp_filter_coefs_4point_bspline, true);
> +}
> diff --git a/drivers/gpu/drm/meson/meson_vpp.h b/drivers/gpu/drm/meson/meson_vpp.h
> new file mode 100644
> index 0000000..98bb85e
> --- /dev/null
> +++ b/drivers/gpu/drm/meson/meson_vpp.h
> @@ -0,0 +1,43 @@
> +/*
> + * Copyright (C) 2016 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong@xxxxxxxxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
> + * 02111-1307, USA.
> + */
> +
> +/* Video Post Process */
> +
> +#ifndef __MESON_VPP_H
> +#define __MESON_VPP_H
> +
> +void meson_vpp_enable_osd1(struct meson_drm *priv);
> +void meson_vpp_disable_osd1(struct meson_drm *priv);
> +
> +void meson_vpp_enable_postblend(struct meson_drm *priv, unsigned int width);
> +void meson_vpp_disable_postblend(struct meson_drm *priv);
> +
> +/* Mux VIU/VPP to ENCI */
> +#define MESON_VIU_VPP_MUX_ENCI 0x5
> +
> +void meson_vpp_setup_mux(struct meson_drm *priv, unsigned int mux);
> +
> +void meson_vpp_setup_interlace_vscaler_osd1(struct meson_drm *priv,
> + struct drm_rect *input);
> +void meson_vpp_disable_interlace_vscaler_osd1(struct meson_drm *priv);
> +
> +void meson_vpp_init(struct meson_drm *priv);
> +
> +#endif /* __MESON_VPP_H */
> --
> 1.9.1
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@xxxxxxxxxxxxxxxxxxxxx
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch