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 <narmstr...@baylibre.com>
---
 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

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to