2020-09-07 08:22:49

by Neil Armstrong

[permalink] [raw]
Subject: [PATCH 0/6] drm/meson: add support for AXG & MIPI-DSI

The Amlogic AXG SoC family has a downgraded VPU with the following
changes :
- Only a single OSD plane, no overlay video plane
- The primary plane doesn't support HW scaling
- The pixels are read directly from DDR without any Canvas module
- Doesn't support HDMI or CVBS
- Ouputs only with ENCL encoder to a DPI-to-DSI Synopsys DW-MIPI-DSI transceiver

The Amlogic AXg SoCs embeds a Synopsys DW-MIPI-DSI transceiver (ver 1.21a), with a custom
glue managing the IP resets, clock and data input similar to the DW-HDMI Glue on other
Amlogic SoCs.

This adds support for the Glue managing the transceiver, mimicing the init flow provided
by Amlogic to setup the ENCl encoder, the glue, the transceiver, the digital D-PHY and the
Analog PHY in the proper way.

The DW-MIPI-DSI transceiver + D-PHY are directly clocked by the VCLK2 clock, which pixel clock
is derived and feeds the ENCL encoder and the VIU pixel reader.

An optional "MEAS" clock can be enabled to measure the delay between each vsync feeding the
DW-MIPI-DSI transceiver.

Neil Armstrong (6):
dt-bindings: display: amlogic,meson-vpu: add bindings for VPU found in
AXG SoCs
dt-bindings: display: add Amlogic MIPI DSI Host Controller bindings
drm/meson: add support for VPU found in AXG SoCs
drm/meson: venc: add ENCL encoder setup for MIPI-DSI output
drm/meson: remove useless recursive components matching
drm/meson: add support for MIPI-DSI transceiver

.../display/amlogic,meson-dw-mipi-dsi.yaml | 115 ++++
.../bindings/display/amlogic,meson-vpu.yaml | 36 +-
drivers/gpu/drm/meson/Kconfig | 7 +
drivers/gpu/drm/meson/Makefile | 1 +
drivers/gpu/drm/meson/meson_crtc.c | 8 +-
drivers/gpu/drm/meson/meson_drv.c | 163 ++---
drivers/gpu/drm/meson/meson_drv.h | 10 +-
drivers/gpu/drm/meson/meson_dw_mipi_dsi.c | 562 ++++++++++++++++++
drivers/gpu/drm/meson/meson_plane.c | 74 ++-
drivers/gpu/drm/meson/meson_registers.h | 1 +
drivers/gpu/drm/meson/meson_venc.c | 230 ++++++-
drivers/gpu/drm/meson/meson_venc.h | 6 +
drivers/gpu/drm/meson/meson_viu.c | 50 +-
drivers/gpu/drm/meson/meson_vpp.c | 6 +-
drivers/gpu/drm/meson/meson_vpp.h | 2 +
15 files changed, 1176 insertions(+), 95 deletions(-)
create mode 100644 Documentation/devicetree/bindings/display/amlogic,meson-dw-mipi-dsi.yaml
create mode 100644 drivers/gpu/drm/meson/meson_dw_mipi_dsi.c

--
2.22.0


2020-09-07 08:23:12

by Neil Armstrong

[permalink] [raw]
Subject: [PATCH 3/6] drm/meson: add support for VPU found in AXG SoCs

The Amlogic AXG SoC family has a downgraded VPU with the following
changes :
- Only a single OSD plane, no overlay video plane
- The primary plane doesn't support HW scaling
- The pixels are read directly from DDR without any Canvas module
- Doesn't support HDMI or CVBS
- Ouputs only with ENCL encoder to a DPI-to-DSI Synopsys DW-MIPI-DSI transceiver

Signed-off-by: Neil Armstrong <[email protected]>
---
drivers/gpu/drm/meson/meson_crtc.c | 8 +-
drivers/gpu/drm/meson/meson_drv.c | 115 ++++++++++++++++--------
drivers/gpu/drm/meson/meson_drv.h | 10 ++-
drivers/gpu/drm/meson/meson_plane.c | 74 +++++++++++++--
drivers/gpu/drm/meson/meson_registers.h | 1 +
drivers/gpu/drm/meson/meson_viu.c | 50 ++++++++++-
drivers/gpu/drm/meson/meson_vpp.c | 6 +-
7 files changed, 215 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/meson/meson_crtc.c b/drivers/gpu/drm/meson/meson_crtc.c
index 2854272dc2d9..430599caa5a0 100644
--- a/drivers/gpu/drm/meson/meson_crtc.c
+++ b/drivers/gpu/drm/meson/meson_crtc.c
@@ -366,7 +366,13 @@ void meson_crtc_irq(struct meson_drm *priv)
writel_relaxed(priv->viu.osd_sc_v_ctrl0,
priv->io_base + _REG(VPP_OSD_VSC_CTRL0));

- if (!priv->viu.osd1_afbcd)
+ /* AXG doesn't use CANVAS since it support a single plane */
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_AXG)) {
+ writel_relaxed(priv->viu.osd1_addr,
+ priv->io_base + _REG(VIU_OSD1_BLK1_CFG_W4));
+ writel_relaxed(priv->viu.osd1_blk2_cfg4,
+ priv->io_base + _REG(VIU_OSD1_BLK2_CFG_W4));
+ } else if (!priv->viu.osd1_afbcd)
meson_canvas_config(priv->canvas, priv->canvas_id_osd1,
priv->viu.osd1_addr,
priv->viu.osd1_stride,
diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
index 8b9c8dd788c4..92346653223f 100644
--- a/drivers/gpu/drm/meson/meson_drv.c
+++ b/drivers/gpu/drm/meson/meson_drv.c
@@ -223,6 +223,7 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
drm->dev_private = priv;
priv->drm = drm;
priv->dev = dev;
+ priv->data = match;
priv->compat = match->compat;
priv->afbcd.ops = match->afbcd_ops;

@@ -255,32 +256,34 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
goto free_drm;
}

- priv->canvas = meson_canvas_get(dev);
- if (IS_ERR(priv->canvas)) {
- ret = PTR_ERR(priv->canvas);
- goto free_drm;
- }
+ if (priv->data->requires_canvas) {
+ priv->canvas = meson_canvas_get(dev);
+ if (IS_ERR(priv->canvas)) {
+ ret = PTR_ERR(priv->canvas);
+ goto free_drm;
+ }

- ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_osd1);
- if (ret)
- goto free_drm;
- ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_0);
- if (ret) {
- meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
- goto free_drm;
- }
- ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_1);
- if (ret) {
- meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
- meson_canvas_free(priv->canvas, priv->canvas_id_vd1_0);
- goto free_drm;
- }
- ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_2);
- if (ret) {
- meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
- meson_canvas_free(priv->canvas, priv->canvas_id_vd1_0);
- meson_canvas_free(priv->canvas, priv->canvas_id_vd1_1);
- goto free_drm;
+ ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_osd1);
+ if (ret)
+ goto free_drm;
+ ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_0);
+ if (ret) {
+ meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
+ goto free_drm;
+ }
+ ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_1);
+ if (ret) {
+ meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
+ meson_canvas_free(priv->canvas, priv->canvas_id_vd1_0);
+ goto free_drm;
+ }
+ ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_2);
+ if (ret) {
+ meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
+ meson_canvas_free(priv->canvas, priv->canvas_id_vd1_0);
+ meson_canvas_free(priv->canvas, priv->canvas_id_vd1_1);
+ goto free_drm;
+ }
}

priv->vsync_irq = platform_get_irq(pdev, 0);
@@ -303,8 +306,8 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
ret = drmm_mode_config_init(drm);
if (ret)
goto free_drm;
- drm->mode_config.max_width = 3840;
- drm->mode_config.max_height = 2160;
+ drm->mode_config.max_width = priv->data->max_width;
+ drm->mode_config.max_height = priv->data->max_height;
drm->mode_config.funcs = &meson_mode_config_funcs;
drm->mode_config.helper_private = &meson_mode_config_helpers;

@@ -322,9 +325,11 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)

/* Encoder Initialization */

- ret = meson_venc_cvbs_create(priv);
- if (ret)
- goto free_drm;
+ if (priv->data->provides_cvbs) {
+ ret = meson_venc_cvbs_create(priv);
+ if (ret)
+ goto free_drm;
+ }

if (has_components) {
ret = component_bind_all(drm->dev, drm);
@@ -334,13 +339,17 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
}
}

- ret = meson_plane_create(priv);
- if (ret)
- goto free_drm;
+ if (priv->data->osd_count) {
+ ret = meson_plane_create(priv);
+ if (ret)
+ goto free_drm;
+ }

- ret = meson_overlay_create(priv);
- if (ret)
- goto free_drm;
+ if (priv->data->vd_count) {
+ ret = meson_overlay_create(priv);
+ if (ret)
+ goto free_drm;
+ }

ret = meson_crtc_create(priv);
if (ret)
@@ -516,20 +525,52 @@ static int meson_drv_probe(struct platform_device *pdev)

static struct meson_drm_match_data meson_drm_gxbb_data = {
.compat = VPU_COMPATIBLE_GXBB,
+ .requires_canvas = true,
+ .provides_cvbs = true,
+ .osd_count = 2,
+ .vd_count = 2,
+ .max_width = 3840,
+ .max_height = 2160,
};

static struct meson_drm_match_data meson_drm_gxl_data = {
.compat = VPU_COMPATIBLE_GXL,
+ .requires_canvas = true,
+ .provides_cvbs = true,
+ .osd_count = 2,
+ .vd_count = 2,
+ .max_width = 3840,
+ .max_height = 2160,
};

static struct meson_drm_match_data meson_drm_gxm_data = {
.compat = VPU_COMPATIBLE_GXM,
.afbcd_ops = &meson_afbcd_gxm_ops,
+ .requires_canvas = true,
+ .provides_cvbs = true,
+ .osd_count = 2,
+ .vd_count = 2,
+ .max_width = 3840,
+ .max_height = 2160,
+};
+
+static struct meson_drm_match_data meson_drm_axg_data = {
+ .compat = VPU_COMPATIBLE_AXG,
+ .osd_count = 1,
+ .vd_count = 0,
+ .max_width = 1920,
+ .max_height = 1080,
};

static struct meson_drm_match_data meson_drm_g12a_data = {
.compat = VPU_COMPATIBLE_G12A,
.afbcd_ops = &meson_afbcd_g12a_ops,
+ .requires_canvas = true,
+ .provides_cvbs = true,
+ .osd_count = 4,
+ .vd_count = 2,
+ .max_width = 3840,
+ .max_height = 2160,
};

static const struct of_device_id dt_match[] = {
@@ -539,6 +580,8 @@ static const struct of_device_id dt_match[] = {
.data = (void *)&meson_drm_gxl_data },
{ .compatible = "amlogic,meson-gxm-vpu",
.data = (void *)&meson_drm_gxm_data },
+ { .compatible = "amlogic,meson-axg-vpu",
+ .data = (void *)&meson_drm_axg_data },
{ .compatible = "amlogic,meson-g12a-vpu",
.data = (void *)&meson_drm_g12a_data },
{}
diff --git a/drivers/gpu/drm/meson/meson_drv.h b/drivers/gpu/drm/meson/meson_drv.h
index 177dac3ca3be..5d67f97ec298 100644
--- a/drivers/gpu/drm/meson/meson_drv.h
+++ b/drivers/gpu/drm/meson/meson_drv.h
@@ -22,12 +22,19 @@ enum vpu_compatible {
VPU_COMPATIBLE_GXBB = 0,
VPU_COMPATIBLE_GXL = 1,
VPU_COMPATIBLE_GXM = 2,
- VPU_COMPATIBLE_G12A = 3,
+ VPU_COMPATIBLE_AXG = 3,
+ VPU_COMPATIBLE_G12A = 4,
};

struct meson_drm_match_data {
enum vpu_compatible compat;
struct meson_afbcd_ops *afbcd_ops;
+ bool requires_canvas;
+ bool provides_cvbs;
+ unsigned int osd_count;
+ unsigned int vd_count;
+ unsigned int max_width;
+ unsigned int max_height;
};

struct meson_drm_soc_limits {
@@ -52,6 +59,7 @@ struct meson_drm {
struct drm_plane *primary_plane;
struct drm_plane *overlay_plane;

+ const struct meson_drm_match_data *data;
const struct meson_drm_soc_limits *limits;

/* Components Data */
diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c
index 35338ed18209..9111b3540bdf 100644
--- a/drivers/gpu/drm/meson/meson_plane.c
+++ b/drivers/gpu/drm/meson/meson_plane.c
@@ -93,6 +93,25 @@ static int meson_plane_atomic_check(struct drm_plane *plane,
false, true);
}

+static int meson_plane_atomic_check_axg(struct drm_plane *plane,
+ struct drm_plane_state *state)
+{
+ struct drm_crtc_state *crtc_state;
+
+ if (!state->crtc)
+ return 0;
+
+ crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
+ if (IS_ERR(crtc_state))
+ return PTR_ERR(crtc_state);
+
+ /* AXG VPU OSD plane doesn't support scaling */
+ return drm_atomic_helper_check_plane_state(state, crtc_state,
+ DRM_PLANE_HELPER_NO_SCALING,
+ DRM_PLANE_HELPER_NO_SCALING,
+ true, true);
+}
+
#define MESON_MOD_AFBC_VALID_BITS (AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | \
AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | \
AFBC_FORMAT_MOD_YTR | \
@@ -125,6 +144,29 @@ static u32 meson_g12a_afbcd_line_stride(struct meson_drm *priv)
return ((line_stride + 1) >> 1) << 1;
}

+static u32 meson_axg_line_stride(struct meson_drm *priv, u32 format)
+{
+ u32 line_stride = 0;
+ u32 bwidth;
+
+ switch (format) {
+ case DRM_FORMAT_RGB565:
+ bwidth = priv->viu.osd1_stride >> 1;
+ line_stride = ((bwidth << 4) + 127) >> 7;
+ break;
+ case DRM_FORMAT_RGB888:
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_XBGR8888:
+ case DRM_FORMAT_ABGR8888:
+ bwidth = priv->viu.osd1_stride >> 2;
+ line_stride = ((bwidth << 5) + 127) >> 7;
+ break;
+ }
+
+ return ((line_stride + 1) >> 1) << 1;
+}
+
static void meson_plane_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
@@ -161,15 +203,20 @@ static void meson_plane_atomic_update(struct drm_plane *plane,
else
priv->viu.osd1_afbcd = false;

- /* Enable OSD and BLK0, set max global alpha */
- priv->viu.osd1_ctrl_stat = OSD_ENABLE |
- (0xFF << OSD_GLOBAL_ALPHA_SHIFT) |
- OSD_BLK0_ENABLE;
+ priv->viu.osd1_ctrl_stat = OSD_ENABLE | OSD_BLK0_ENABLE;
+
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_AXG))
+ priv->viu.osd1_ctrl_stat |= 0x100 << OSD_GLOBAL_ALPHA_SHIFT;
+ else
+ priv->viu.osd1_ctrl_stat |= 0xFF << OSD_GLOBAL_ALPHA_SHIFT;

priv->viu.osd1_ctrl_stat2 = readl(priv->io_base +
_REG(VIU_OSD1_CTRL_STAT2));

- canvas_id_osd1 = priv->canvas_id_osd1;
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_AXG))
+ canvas_id_osd1 = 0x40;
+ else
+ canvas_id_osd1 = priv->canvas_id_osd1;

/* Set up BLK0 to point to the right canvas */
priv->viu.osd1_blk0_cfg[0] = canvas_id_osd1 << OSD_CANVAS_SEL;
@@ -366,7 +413,10 @@ static void meson_plane_atomic_update(struct drm_plane *plane,
priv->viu.osd1_height = fb->height;
priv->viu.osd1_width = fb->width;

- if (priv->viu.osd1_afbcd) {
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_AXG))
+ priv->viu.osd1_blk2_cfg4 = meson_axg_line_stride(priv,
+ fb->format->format);
+ else if (priv->viu.osd1_afbcd) {
priv->afbcd.modifier = fb->modifier;
priv->afbcd.format = fb->format->format;

@@ -413,6 +463,13 @@ static void meson_plane_atomic_disable(struct drm_plane *plane,
priv->viu.osd1_enabled = false;
}

+static const struct drm_plane_helper_funcs meson_plane_helper_funcs_axg = {
+ .atomic_check = meson_plane_atomic_check_axg,
+ .atomic_disable = meson_plane_atomic_disable,
+ .atomic_update = meson_plane_atomic_update,
+ .prepare_fb = drm_gem_fb_prepare_fb,
+};
+
static const struct drm_plane_helper_funcs meson_plane_helper_funcs = {
.atomic_check = meson_plane_atomic_check,
.atomic_disable = meson_plane_atomic_disable,
@@ -550,7 +607,10 @@ int meson_plane_create(struct meson_drm *priv)
format_modifiers,
DRM_PLANE_TYPE_PRIMARY, "meson_primary_plane");

- drm_plane_helper_add(plane, &meson_plane_helper_funcs);
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_AXG))
+ drm_plane_helper_add(plane, &meson_plane_helper_funcs_axg);
+ else
+ drm_plane_helper_add(plane, &meson_plane_helper_funcs);

/* For now, OSD Primary plane is always on the front */
drm_plane_create_zpos_immutable_property(plane, 1);
diff --git a/drivers/gpu/drm/meson/meson_registers.h b/drivers/gpu/drm/meson/meson_registers.h
index 446e7961da48..18396b59e6cb 100644
--- a/drivers/gpu/drm/meson/meson_registers.h
+++ b/drivers/gpu/drm/meson/meson_registers.h
@@ -588,6 +588,7 @@
#define VPP_OSD_SCALE_COEF_IDX 0x1dcc
#define VPP_OSD_SCALE_COEF 0x1dcd
#define VPP_INT_LINE_NUM 0x1dce
+#define VPP_MATRIX_CLIP 0x1dde

#define VPP_WRAP_OSD1_MATRIX_COEF00_01 0x3d60
#define VPP_WRAP_OSD1_MATRIX_COEF02_10 0x3d61
diff --git a/drivers/gpu/drm/meson/meson_viu.c b/drivers/gpu/drm/meson/meson_viu.c
index aede0c67a57f..9b644e598211 100644
--- a/drivers/gpu/drm/meson/meson_viu.c
+++ b/drivers/gpu/drm/meson/meson_viu.c
@@ -423,19 +423,63 @@ void meson_viu_init(struct meson_drm *priv)

/* On GXL/GXM, Use the 10bit HDR conversion matrix */
if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
- meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
+ meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL) ||
+ meson_vpu_is_compatible(priv, VPU_COMPATIBLE_AXG))
meson_viu_load_matrix(priv);
else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff,
true);

+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_AXG)) {
+ writel_bits_relaxed(BIT(0), BIT(0),
+ priv->io_base + _REG(VPP_MATRIX_CTRL));
+ writel_bits_relaxed(0x3 << 8, 0,
+ priv->io_base + _REG(VPP_MATRIX_CTRL));
+
+ writel_relaxed(0x0fc00e00,
+ priv->io_base + _REG(VPP_MATRIX_PRE_OFFSET0_1));
+ writel_relaxed(0x00000e00,
+ priv->io_base + _REG(VPP_MATRIX_PRE_OFFSET2));
+
+ /*
+ * ycbcr limit range, 709 to RGB
+ * -16 1.164 0 1.793 0
+ * -128 1.164 -0.213 -0.534 0
+ * -128 1.164 2.115 0 0
+ */
+ writel_relaxed(0x04a80000,
+ priv->io_base + _REG(VPP_MATRIX_COEF00_01));
+ writel_relaxed(0x072c04a8,
+ priv->io_base + _REG(VPP_MATRIX_COEF02_10));
+ writel_relaxed(0x1f261ddd,
+ priv->io_base + _REG(VPP_MATRIX_COEF11_12));
+ writel_relaxed(0x04a80876,
+ priv->io_base + _REG(VPP_MATRIX_COEF20_21));
+ writel_relaxed(0x0, priv->io_base + _REG(VPP_MATRIX_COEF22));
+ writel_relaxed(0x0, priv->io_base + _REG(VPP_MATRIX_OFFSET0_1));
+ writel_relaxed(0x0, priv->io_base + _REG(VPP_MATRIX_OFFSET2));
+
+ writel_bits_relaxed(0x1f << 3, 0,
+ priv->io_base + _REG(VPP_MATRIX_CLIP));
+ }
+
/* Initialize OSD1 fifo control register */
reg = VIU_OSD_DDR_PRIORITY_URGENT |
- VIU_OSD_HOLD_FIFO_LINES(31) |
- VIU_OSD_FIFO_DEPTH_VAL(32) | /* fifo_depth_val: 32*8=256 */
VIU_OSD_WORDS_PER_BURST(4) | /* 4 words in 1 burst */
VIU_OSD_FIFO_LIMITS(2); /* fifo_lim: 2*16=32 */

+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_AXG))
+ reg |= VIU_OSD_HOLD_FIFO_LINES(24);
+ else
+ reg |= VIU_OSD_HOLD_FIFO_LINES(31);
+
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
+ meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL) ||
+ meson_vpu_is_compatible(priv, VPU_COMPATIBLE_AXG))
+ reg |= VIU_OSD_FIFO_DEPTH_VAL(32); /* fifo_depth_val: 32*8=256 */
+ else
+ reg |= VIU_OSD_FIFO_DEPTH_VAL(64); /* fifo_depth_val: 64*8=512 */
+
if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
reg |= VIU_OSD_BURST_LENGTH_32;
else
diff --git a/drivers/gpu/drm/meson/meson_vpp.c b/drivers/gpu/drm/meson/meson_vpp.c
index 154837688ab0..069f527d42c6 100644
--- a/drivers/gpu/drm/meson/meson_vpp.c
+++ b/drivers/gpu/drm/meson/meson_vpp.c
@@ -91,7 +91,8 @@ static void meson_vpp_write_vd_scaling_filter_coefs(struct meson_drm *priv,
void meson_vpp_init(struct meson_drm *priv)
{
/* set dummy data default YUV black */
- if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL) ||
+ meson_vpu_is_compatible(priv, VPU_COMPATIBLE_AXG))
writel_relaxed(0x108080, priv->io_base + _REG(VPP_DUMMY_DATA1));
else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM)) {
writel_bits_relaxed(0xff << 16, 0xff << 16,
@@ -107,6 +108,9 @@ void meson_vpp_init(struct meson_drm *priv)
if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
writel_relaxed(VPP_OFIFO_SIZE_DEFAULT,
priv->io_base + _REG(VPP_OFIFO_SIZE));
+ else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_AXG))
+ writel_bits_relaxed(VPP_OFIFO_SIZE_MASK, 0x400,
+ priv->io_base + _REG(VPP_OFIFO_SIZE));
else
writel_bits_relaxed(VPP_OFIFO_SIZE_MASK, 0x77f,
priv->io_base + _REG(VPP_OFIFO_SIZE));
--
2.22.0

2020-09-07 08:23:24

by Neil Armstrong

[permalink] [raw]
Subject: [PATCH 1/6] dt-bindings: display: amlogic,meson-vpu: add bindings for VPU found in AXG SoCs

The Amlogic AXG SoC family has a downgraded VPU supporting only MIPI-DSI output
after it's ENCL DPI encoder output.

Signed-off-by: Neil Armstrong <[email protected]>
---
.../bindings/display/amlogic,meson-vpu.yaml | 36 +++++++++++++++++--
1 file changed, 33 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/amlogic,meson-vpu.yaml b/Documentation/devicetree/bindings/display/amlogic,meson-vpu.yaml
index a8d202c9d004..e2e7d99d8ace 100644
--- a/Documentation/devicetree/bindings/display/amlogic,meson-vpu.yaml
+++ b/Documentation/devicetree/bindings/display/amlogic,meson-vpu.yaml
@@ -31,8 +31,10 @@ description: |

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.
+ On the AXG family, the Video Input Unit direclty reads from DDR memory.
This part is also in charge of the CSC (Colorspace Conversion).
It can handle 2 OSD Planes and 2 Video Planes.
+ On the AXG family, only a single OSD plane without scalins is supported.

VPP: Video Post Processing
--------------------------
@@ -49,11 +51,13 @@ description: |
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
+ - ENCL : LCD DPI 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.
+ On the AXG and G12A family, the ENCL is connected to a DPI-to-DSI
+ transceiver.

properties:
compatible:
@@ -65,6 +69,7 @@ properties:
- amlogic,meson-gxm-vpu # GXM (S912)
- const: amlogic,meson-gx-vpu
- enum:
+ - amlogic,meson-axg-vpu # AXG (A113D, A113X)
- amlogic,meson-g12a-vpu # G12A (S905X2, S905Y2, S905D2)

reg:
@@ -92,6 +97,11 @@ properties:
description:
A port node pointing to the HDMI-TX port node.

+ port@2:
+ type: object
+ description:
+ A port node pointing to the DPI port node.
+
"#address-cells":
const: 1

@@ -102,11 +112,31 @@ required:
- compatible
- reg
- interrupts
- - port@0
- - port@1
- "#address-cells"
- "#size-cells"

+allOf:
+ - if:
+ properties:
+ compatible:
+ enum:
+ - amlogic,meson-gx-vpu
+ - amlogic,meson-g12a-vpu
+
+ then:
+ required:
+ - port@0
+ - port@1
+ - if:
+ properties:
+ compatible:
+ enum:
+ - amlogic,meson-axg-vpu
+
+ then:
+ required:
+ - port@2
+
additionalProperties: false

examples:
--
2.22.0

2020-09-15 22:53:37

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH 1/6] dt-bindings: display: amlogic,meson-vpu: add bindings for VPU found in AXG SoCs

On Mon, Sep 07, 2020 at 10:18:20AM +0200, Neil Armstrong wrote:
> The Amlogic AXG SoC family has a downgraded VPU supporting only MIPI-DSI output
> after it's ENCL DPI encoder output.
>
> Signed-off-by: Neil Armstrong <[email protected]>
> ---
> .../bindings/display/amlogic,meson-vpu.yaml | 36 +++++++++++++++++--
> 1 file changed, 33 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/display/amlogic,meson-vpu.yaml b/Documentation/devicetree/bindings/display/amlogic,meson-vpu.yaml
> index a8d202c9d004..e2e7d99d8ace 100644
> --- a/Documentation/devicetree/bindings/display/amlogic,meson-vpu.yaml
> +++ b/Documentation/devicetree/bindings/display/amlogic,meson-vpu.yaml
> @@ -31,8 +31,10 @@ description: |
>
> 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.
> + On the AXG family, the Video Input Unit direclty reads from DDR memory.
> This part is also in charge of the CSC (Colorspace Conversion).
> It can handle 2 OSD Planes and 2 Video Planes.
> + On the AXG family, only a single OSD plane without scalins is supported.

s/scalins/scaling/ ?

Otherwise,

Reviewed-by: Rob Herring <[email protected]>