Merge tag 'v5.12-rc4' into next
[linux-2.6-microblaze.git] / drivers / gpu / drm / mediatek / mtk_drm_ddp_comp.c
index 3064eac..75bc00e 100644 (file)
@@ -9,12 +9,12 @@
 #include <linux/clk.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
-#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/soc/mediatek/mtk-cmdq.h>
 #include <drm/drm_print.h>
 
+#include "mtk_disp_drv.h"
 #include "mtk_drm_drv.h"
 #include "mtk_drm_plane.h"
 #include "mtk_drm_ddp_comp.h"
 #define DISP_AAL_EN                            0x0000
 #define DISP_AAL_SIZE                          0x0030
 
-#define DISP_CCORR_EN                          0x0000
-#define CCORR_EN                               BIT(0)
-#define DISP_CCORR_CFG                         0x0020
-#define CCORR_RELAY_MODE                       BIT(0)
-#define CCORR_ENGINE_EN                                BIT(1)
-#define CCORR_GAMMA_OFF                                BIT(2)
-#define CCORR_WGAMUT_SRC_CLIP                  BIT(3)
-#define DISP_CCORR_SIZE                                0x0030
-#define DISP_CCORR_COEF_0                      0x0080
-#define DISP_CCORR_COEF_1                      0x0084
-#define DISP_CCORR_COEF_2                      0x0088
-#define DISP_CCORR_COEF_3                      0x008C
-#define DISP_CCORR_COEF_4                      0x0090
-
 #define DISP_DITHER_EN                         0x0000
 #define DITHER_EN                              BIT(0)
 #define DISP_DITHER_CFG                                0x0020
 #define DITHER_RELAY_MODE                      BIT(0)
+#define DITHER_ENGINE_EN                       BIT(1)
 #define DISP_DITHER_SIZE                       0x0030
 
-#define DISP_GAMMA_EN                          0x0000
-#define DISP_GAMMA_CFG                         0x0020
-#define DISP_GAMMA_SIZE                                0x0030
-#define DISP_GAMMA_LUT                         0x0700
-
 #define LUT_10BIT_MASK                         0x03ff
 
 #define OD_RELAYMODE                           BIT(0)
@@ -68,9 +50,6 @@
 
 #define AAL_EN                                 BIT(0)
 
-#define GAMMA_EN                               BIT(0)
-#define GAMMA_LUT_EN                           BIT(1)
-
 #define DISP_DITHERING                         BIT(2)
 #define DITHER_LSB_ERR_SHIFT_R(x)              (((x) & 0x7) << 28)
 #define DITHER_OVFLW_BIT_R(x)                  (((x) & 0x7) << 24)
 #define DITHER_ADD_LSHIFT_G(x)                 (((x) & 0x7) << 4)
 #define DITHER_ADD_RSHIFT_G(x)                 (((x) & 0x7) << 0)
 
+struct mtk_ddp_comp_dev {
+       struct clk *clk;
+       void __iomem *regs;
+       struct cmdq_client_reg cmdq_reg;
+};
+
 void mtk_ddp_write(struct cmdq_pkt *cmdq_pkt, unsigned int value,
-                  struct mtk_ddp_comp *comp, unsigned int offset)
+                  struct cmdq_client_reg *cmdq_reg, void __iomem *regs,
+                  unsigned int offset)
 {
 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
        if (cmdq_pkt)
-               cmdq_pkt_write(cmdq_pkt, comp->subsys,
-                              comp->regs_pa + offset, value);
+               cmdq_pkt_write(cmdq_pkt, cmdq_reg->subsys,
+                              cmdq_reg->offset + offset, value);
        else
 #endif
-               writel(value, comp->regs + offset);
+               writel(value, regs + offset);
 }
 
 void mtk_ddp_write_relaxed(struct cmdq_pkt *cmdq_pkt, unsigned int value,
-                          struct mtk_ddp_comp *comp,
+                          struct cmdq_client_reg *cmdq_reg, void __iomem *regs,
                           unsigned int offset)
 {
 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
        if (cmdq_pkt)
-               cmdq_pkt_write(cmdq_pkt, comp->subsys,
-                              comp->regs_pa + offset, value);
+               cmdq_pkt_write(cmdq_pkt, cmdq_reg->subsys,
+                              cmdq_reg->offset + offset, value);
        else
 #endif
-               writel_relaxed(value, comp->regs + offset);
+               writel_relaxed(value, regs + offset);
 }
 
-void mtk_ddp_write_mask(struct cmdq_pkt *cmdq_pkt,
-                       unsigned int value,
-                       struct mtk_ddp_comp *comp,
-                       unsigned int offset,
-                       unsigned int mask)
+void mtk_ddp_write_mask(struct cmdq_pkt *cmdq_pkt, unsigned int value,
+                       struct cmdq_client_reg *cmdq_reg, void __iomem *regs,
+                       unsigned int offset, unsigned int mask)
 {
 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
        if (cmdq_pkt) {
-               cmdq_pkt_write_mask(cmdq_pkt, comp->subsys,
-                                   comp->regs_pa + offset, value, mask);
+               cmdq_pkt_write_mask(cmdq_pkt, cmdq_reg->subsys,
+                                   cmdq_reg->offset + offset, value, mask);
        } else {
 #endif
-               u32 tmp = readl(comp->regs + offset);
+               u32 tmp = readl(regs + offset);
 
                tmp = (tmp & ~mask) | (value & mask);
-               writel(tmp, comp->regs + offset);
+               writel(tmp, regs + offset);
 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
        }
 #endif
 }
 
-void mtk_dither_set(struct mtk_ddp_comp *comp, unsigned int bpc,
-                   unsigned int CFG, struct cmdq_pkt *cmdq_pkt)
+static int mtk_ddp_clk_enable(struct device *dev)
+{
+       struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
+
+       return clk_prepare_enable(priv->clk);
+}
+
+static void mtk_ddp_clk_disable(struct device *dev)
+{
+       struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
+
+       clk_disable_unprepare(priv->clk);
+}
+
+void mtk_dither_set_common(void __iomem *regs, struct cmdq_client_reg *cmdq_reg,
+                          unsigned int bpc, unsigned int cfg,
+                          unsigned int dither_en, struct cmdq_pkt *cmdq_pkt)
 {
        /* If bpc equal to 0, the dithering function didn't be enabled */
        if (bpc == 0)
                return;
 
        if (bpc >= MTK_MIN_BPC) {
-               mtk_ddp_write(cmdq_pkt, 0, comp, DISP_DITHER_5);
-               mtk_ddp_write(cmdq_pkt, 0, comp, DISP_DITHER_7);
+               mtk_ddp_write(cmdq_pkt, 0, cmdq_reg, regs, DISP_DITHER_5);
+               mtk_ddp_write(cmdq_pkt, 0, cmdq_reg, regs, DISP_DITHER_7);
                mtk_ddp_write(cmdq_pkt,
                              DITHER_LSB_ERR_SHIFT_R(MTK_MAX_BPC - bpc) |
                              DITHER_ADD_LSHIFT_R(MTK_MAX_BPC - bpc) |
                              DITHER_NEW_BIT_MODE,
-                             comp, DISP_DITHER_15);
+                             cmdq_reg, regs, DISP_DITHER_15);
                mtk_ddp_write(cmdq_pkt,
                              DITHER_LSB_ERR_SHIFT_B(MTK_MAX_BPC - bpc) |
                              DITHER_ADD_LSHIFT_B(MTK_MAX_BPC - bpc) |
                              DITHER_LSB_ERR_SHIFT_G(MTK_MAX_BPC - bpc) |
                              DITHER_ADD_LSHIFT_G(MTK_MAX_BPC - bpc),
-                             comp, DISP_DITHER_16);
-               mtk_ddp_write(cmdq_pkt, DISP_DITHERING, comp, CFG);
+                             cmdq_reg, regs, DISP_DITHER_16);
+               mtk_ddp_write(cmdq_pkt, dither_en, cmdq_reg, regs, cfg);
        }
 }
 
-static void mtk_od_config(struct mtk_ddp_comp *comp, unsigned int w,
-                         unsigned int h, unsigned int vrefresh,
-                         unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
+static void mtk_dither_set(struct device *dev, unsigned int bpc,
+                   unsigned int cfg, struct cmdq_pkt *cmdq_pkt)
 {
-       mtk_ddp_write(cmdq_pkt, w << 16 | h, comp, DISP_OD_SIZE);
-       mtk_ddp_write(cmdq_pkt, OD_RELAYMODE, comp, DISP_OD_CFG);
-       mtk_dither_set(comp, bpc, DISP_OD_CFG, cmdq_pkt);
-}
+       struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
 
-static void mtk_od_start(struct mtk_ddp_comp *comp)
-{
-       writel(1, comp->regs + DISP_OD_EN);
+       mtk_dither_set_common(priv->regs, &priv->cmdq_reg, bpc, cfg,
+                             DISP_DITHERING, cmdq_pkt);
 }
 
-static void mtk_ufoe_start(struct mtk_ddp_comp *comp)
+static void mtk_od_config(struct device *dev, unsigned int w,
+                         unsigned int h, unsigned int vrefresh,
+                         unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
 {
-       writel(UFO_BYPASS, comp->regs + DISP_REG_UFO_START);
-}
+       struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
 
-static void mtk_aal_config(struct mtk_ddp_comp *comp, unsigned int w,
-                          unsigned int h, unsigned int vrefresh,
-                          unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
-{
-       mtk_ddp_write(cmdq_pkt, h << 16 | w, comp, DISP_AAL_SIZE);
+       mtk_ddp_write(cmdq_pkt, w << 16 | h, &priv->cmdq_reg, priv->regs, DISP_OD_SIZE);
+       mtk_ddp_write(cmdq_pkt, OD_RELAYMODE, &priv->cmdq_reg, priv->regs, DISP_OD_CFG);
+       mtk_dither_set(dev, bpc, DISP_OD_CFG, cmdq_pkt);
 }
 
-static void mtk_aal_start(struct mtk_ddp_comp *comp)
+static void mtk_od_start(struct device *dev)
 {
-       writel(AAL_EN, comp->regs + DISP_AAL_EN);
-}
+       struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
 
-static void mtk_aal_stop(struct mtk_ddp_comp *comp)
-{
-       writel_relaxed(0x0, comp->regs + DISP_AAL_EN);
+       writel(1, priv->regs + DISP_OD_EN);
 }
 
-static void mtk_ccorr_config(struct mtk_ddp_comp *comp, unsigned int w,
-                            unsigned int h, unsigned int vrefresh,
-                            unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
+static void mtk_ufoe_start(struct device *dev)
 {
-       mtk_ddp_write(cmdq_pkt, h << 16 | w, comp, DISP_CCORR_SIZE);
-       mtk_ddp_write(cmdq_pkt, CCORR_ENGINE_EN, comp, DISP_CCORR_CFG);
-}
+       struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
 
-static void mtk_ccorr_start(struct mtk_ddp_comp *comp)
-{
-       writel(CCORR_EN, comp->regs + DISP_CCORR_EN);
+       writel(UFO_BYPASS, priv->regs + DISP_REG_UFO_START);
 }
 
-static void mtk_ccorr_stop(struct mtk_ddp_comp *comp)
+static void mtk_aal_config(struct device *dev, unsigned int w,
+                          unsigned int h, unsigned int vrefresh,
+                          unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
 {
-       writel_relaxed(0x0, comp->regs + DISP_CCORR_EN);
+       struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
+
+       mtk_ddp_write(cmdq_pkt, w << 16 | h, &priv->cmdq_reg, priv->regs, DISP_AAL_SIZE);
 }
 
-/* Converts a DRM S31.32 value to the HW S1.10 format. */
-static u16 mtk_ctm_s31_32_to_s1_10(u64 in)
+static void mtk_aal_gamma_set(struct device *dev, struct drm_crtc_state *state)
 {
-       u16 r;
+       struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
 
-       /* Sign bit. */
-       r = in & BIT_ULL(63) ? BIT(11) : 0;
+       mtk_gamma_set_common(priv->regs, state);
+}
 
-       if ((in & GENMASK_ULL(62, 33)) > 0) {
-               /* identity value 0x100000000 -> 0x400, */
-               /* if bigger this, set it to max 0x7ff. */
-               r |= GENMASK(10, 0);
-       } else {
-               /* take the 11 most important bits. */
-               r |= (in >> 22) & GENMASK(10, 0);
-       }
+static void mtk_aal_start(struct device *dev)
+{
+       struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
 
-       return r;
+       writel(AAL_EN, priv->regs + DISP_AAL_EN);
 }
 
-static void mtk_ccorr_ctm_set(struct mtk_ddp_comp *comp,
-                             struct drm_crtc_state *state)
+static void mtk_aal_stop(struct device *dev)
 {
-       struct drm_property_blob *blob = state->ctm;
-       struct drm_color_ctm *ctm;
-       const u64 *input;
-       uint16_t coeffs[9] = { 0 };
-       int i;
-       struct cmdq_pkt *cmdq_pkt = NULL;
-
-       if (!blob)
-               return;
+       struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
 
-       ctm = (struct drm_color_ctm *)blob->data;
-       input = ctm->matrix;
-
-       for (i = 0; i < ARRAY_SIZE(coeffs); i++)
-               coeffs[i] = mtk_ctm_s31_32_to_s1_10(input[i]);
-
-       mtk_ddp_write(cmdq_pkt, coeffs[0] << 16 | coeffs[1],
-                     comp, DISP_CCORR_COEF_0);
-       mtk_ddp_write(cmdq_pkt, coeffs[2] << 16 | coeffs[3],
-                     comp, DISP_CCORR_COEF_1);
-       mtk_ddp_write(cmdq_pkt, coeffs[4] << 16 | coeffs[5],
-                     comp, DISP_CCORR_COEF_2);
-       mtk_ddp_write(cmdq_pkt, coeffs[6] << 16 | coeffs[7],
-                     comp, DISP_CCORR_COEF_3);
-       mtk_ddp_write(cmdq_pkt, coeffs[8] << 16,
-                     comp, DISP_CCORR_COEF_4);
+       writel_relaxed(0x0, priv->regs + DISP_AAL_EN);
 }
 
-static void mtk_dither_config(struct mtk_ddp_comp *comp, unsigned int w,
+static void mtk_dither_config(struct device *dev, unsigned int w,
                              unsigned int h, unsigned int vrefresh,
                              unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
 {
-       mtk_ddp_write(cmdq_pkt, h << 16 | w, comp, DISP_DITHER_SIZE);
-       mtk_ddp_write(cmdq_pkt, DITHER_RELAY_MODE, comp, DISP_DITHER_CFG);
-}
-
-static void mtk_dither_start(struct mtk_ddp_comp *comp)
-{
-       writel(DITHER_EN, comp->regs + DISP_DITHER_EN);
-}
+       struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
 
-static void mtk_dither_stop(struct mtk_ddp_comp *comp)
-{
-       writel_relaxed(0x0, comp->regs + DISP_DITHER_EN);
+       mtk_ddp_write(cmdq_pkt, h << 16 | w, &priv->cmdq_reg, priv->regs, DISP_DITHER_SIZE);
+       mtk_ddp_write(cmdq_pkt, DITHER_RELAY_MODE, &priv->cmdq_reg, priv->regs, DISP_DITHER_CFG);
+       mtk_dither_set_common(priv->regs, &priv->cmdq_reg, bpc, DISP_DITHER_CFG,
+                             DITHER_ENGINE_EN, cmdq_pkt);
 }
 
-static void mtk_gamma_config(struct mtk_ddp_comp *comp, unsigned int w,
-                            unsigned int h, unsigned int vrefresh,
-                            unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
+static void mtk_dither_start(struct device *dev)
 {
-       mtk_ddp_write(cmdq_pkt, h << 16 | w, comp, DISP_GAMMA_SIZE);
-       mtk_dither_set(comp, bpc, DISP_GAMMA_CFG, cmdq_pkt);
-}
+       struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
 
-static void mtk_gamma_start(struct mtk_ddp_comp *comp)
-{
-       writel(GAMMA_EN, comp->regs  + DISP_GAMMA_EN);
+       writel(DITHER_EN, priv->regs + DISP_DITHER_EN);
 }
 
-static void mtk_gamma_stop(struct mtk_ddp_comp *comp)
+static void mtk_dither_stop(struct device *dev)
 {
-       writel_relaxed(0x0, comp->regs  + DISP_GAMMA_EN);
-}
+       struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
 
-static void mtk_gamma_set(struct mtk_ddp_comp *comp,
-                         struct drm_crtc_state *state)
-{
-       unsigned int i, reg;
-       struct drm_color_lut *lut;
-       void __iomem *lut_base;
-       u32 word;
-
-       if (state->gamma_lut) {
-               reg = readl(comp->regs + DISP_GAMMA_CFG);
-               reg = reg | GAMMA_LUT_EN;
-               writel(reg, comp->regs + DISP_GAMMA_CFG);
-               lut_base = comp->regs + DISP_GAMMA_LUT;
-               lut = (struct drm_color_lut *)state->gamma_lut->data;
-               for (i = 0; i < MTK_LUT_SIZE; i++) {
-                       word = (((lut[i].red >> 6) & LUT_10BIT_MASK) << 20) +
-                               (((lut[i].green >> 6) & LUT_10BIT_MASK) << 10) +
-                               ((lut[i].blue >> 6) & LUT_10BIT_MASK);
-                       writel(word, (lut_base + i * 4));
-               }
-       }
+       writel_relaxed(0x0, priv->regs + DISP_DITHER_EN);
 }
 
 static const struct mtk_ddp_comp_funcs ddp_aal = {
-       .gamma_set = mtk_gamma_set,
+       .clk_enable = mtk_ddp_clk_enable,
+       .clk_disable = mtk_ddp_clk_disable,
+       .gamma_set = mtk_aal_gamma_set,
        .config = mtk_aal_config,
        .start = mtk_aal_start,
        .stop = mtk_aal_stop,
 };
 
 static const struct mtk_ddp_comp_funcs ddp_ccorr = {
+       .clk_enable = mtk_ccorr_clk_enable,
+       .clk_disable = mtk_ccorr_clk_disable,
        .config = mtk_ccorr_config,
        .start = mtk_ccorr_start,
        .stop = mtk_ccorr_stop,
        .ctm_set = mtk_ccorr_ctm_set,
 };
 
+static const struct mtk_ddp_comp_funcs ddp_color = {
+       .clk_enable = mtk_color_clk_enable,
+       .clk_disable = mtk_color_clk_disable,
+       .config = mtk_color_config,
+       .start = mtk_color_start,
+};
+
 static const struct mtk_ddp_comp_funcs ddp_dither = {
+       .clk_enable = mtk_ddp_clk_enable,
+       .clk_disable = mtk_ddp_clk_disable,
        .config = mtk_dither_config,
        .start = mtk_dither_start,
        .stop = mtk_dither_stop,
 };
 
+static const struct mtk_ddp_comp_funcs ddp_dpi = {
+       .start = mtk_dpi_start,
+       .stop = mtk_dpi_stop,
+};
+
+static const struct mtk_ddp_comp_funcs ddp_dsi = {
+       .start = mtk_dsi_ddp_start,
+       .stop = mtk_dsi_ddp_stop,
+};
+
 static const struct mtk_ddp_comp_funcs ddp_gamma = {
+       .clk_enable = mtk_gamma_clk_enable,
+       .clk_disable = mtk_gamma_clk_disable,
        .gamma_set = mtk_gamma_set,
        .config = mtk_gamma_config,
        .start = mtk_gamma_start,
@@ -349,11 +299,43 @@ static const struct mtk_ddp_comp_funcs ddp_gamma = {
 };
 
 static const struct mtk_ddp_comp_funcs ddp_od = {
+       .clk_enable = mtk_ddp_clk_enable,
+       .clk_disable = mtk_ddp_clk_disable,
        .config = mtk_od_config,
        .start = mtk_od_start,
 };
 
+static const struct mtk_ddp_comp_funcs ddp_ovl = {
+       .clk_enable = mtk_ovl_clk_enable,
+       .clk_disable = mtk_ovl_clk_disable,
+       .config = mtk_ovl_config,
+       .start = mtk_ovl_start,
+       .stop = mtk_ovl_stop,
+       .enable_vblank = mtk_ovl_enable_vblank,
+       .disable_vblank = mtk_ovl_disable_vblank,
+       .supported_rotations = mtk_ovl_supported_rotations,
+       .layer_nr = mtk_ovl_layer_nr,
+       .layer_check = mtk_ovl_layer_check,
+       .layer_config = mtk_ovl_layer_config,
+       .bgclr_in_on = mtk_ovl_bgclr_in_on,
+       .bgclr_in_off = mtk_ovl_bgclr_in_off,
+};
+
+static const struct mtk_ddp_comp_funcs ddp_rdma = {
+       .clk_enable = mtk_rdma_clk_enable,
+       .clk_disable = mtk_rdma_clk_disable,
+       .config = mtk_rdma_config,
+       .start = mtk_rdma_start,
+       .stop = mtk_rdma_stop,
+       .enable_vblank = mtk_rdma_enable_vblank,
+       .disable_vblank = mtk_rdma_disable_vblank,
+       .layer_nr = mtk_rdma_layer_nr,
+       .layer_config = mtk_rdma_layer_config,
+};
+
 static const struct mtk_ddp_comp_funcs ddp_ufoe = {
+       .clk_enable = mtk_ddp_clk_enable,
+       .clk_disable = mtk_ddp_clk_disable,
        .start = mtk_ufoe_start,
 };
 
@@ -387,36 +369,37 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
        [DDP_COMPONENT_AAL1]    = { MTK_DISP_AAL,       1, &ddp_aal },
        [DDP_COMPONENT_BLS]     = { MTK_DISP_BLS,       0, NULL },
        [DDP_COMPONENT_CCORR]   = { MTK_DISP_CCORR,     0, &ddp_ccorr },
-       [DDP_COMPONENT_COLOR0]  = { MTK_DISP_COLOR,     0, NULL },
-       [DDP_COMPONENT_COLOR1]  = { MTK_DISP_COLOR,     1, NULL },
+       [DDP_COMPONENT_COLOR0]  = { MTK_DISP_COLOR,     0, &ddp_color },
+       [DDP_COMPONENT_COLOR1]  = { MTK_DISP_COLOR,     1, &ddp_color },
        [DDP_COMPONENT_DITHER]  = { MTK_DISP_DITHER,    0, &ddp_dither },
-       [DDP_COMPONENT_DPI0]    = { MTK_DPI,            0, NULL },
-       [DDP_COMPONENT_DPI1]    = { MTK_DPI,            1, NULL },
-       [DDP_COMPONENT_DSI0]    = { MTK_DSI,            0, NULL },
-       [DDP_COMPONENT_DSI1]    = { MTK_DSI,            1, NULL },
-       [DDP_COMPONENT_DSI2]    = { MTK_DSI,            2, NULL },
-       [DDP_COMPONENT_DSI3]    = { MTK_DSI,            3, NULL },
+       [DDP_COMPONENT_DPI0]    = { MTK_DPI,            0, &ddp_dpi },
+       [DDP_COMPONENT_DPI1]    = { MTK_DPI,            1, &ddp_dpi },
+       [DDP_COMPONENT_DSI0]    = { MTK_DSI,            0, &ddp_dsi },
+       [DDP_COMPONENT_DSI1]    = { MTK_DSI,            1, &ddp_dsi },
+       [DDP_COMPONENT_DSI2]    = { MTK_DSI,            2, &ddp_dsi },
+       [DDP_COMPONENT_DSI3]    = { MTK_DSI,            3, &ddp_dsi },
        [DDP_COMPONENT_GAMMA]   = { MTK_DISP_GAMMA,     0, &ddp_gamma },
        [DDP_COMPONENT_OD0]     = { MTK_DISP_OD,        0, &ddp_od },
        [DDP_COMPONENT_OD1]     = { MTK_DISP_OD,        1, &ddp_od },
-       [DDP_COMPONENT_OVL0]    = { MTK_DISP_OVL,       0, NULL },
-       [DDP_COMPONENT_OVL1]    = { MTK_DISP_OVL,       1, NULL },
-       [DDP_COMPONENT_OVL_2L0] = { MTK_DISP_OVL_2L,    0, NULL },
-       [DDP_COMPONENT_OVL_2L1] = { MTK_DISP_OVL_2L,    1, NULL },
+       [DDP_COMPONENT_OVL0]    = { MTK_DISP_OVL,       0, &ddp_ovl },
+       [DDP_COMPONENT_OVL1]    = { MTK_DISP_OVL,       1, &ddp_ovl },
+       [DDP_COMPONENT_OVL_2L0] = { MTK_DISP_OVL_2L,    0, &ddp_ovl },
+       [DDP_COMPONENT_OVL_2L1] = { MTK_DISP_OVL_2L,    1, &ddp_ovl },
        [DDP_COMPONENT_PWM0]    = { MTK_DISP_PWM,       0, NULL },
        [DDP_COMPONENT_PWM1]    = { MTK_DISP_PWM,       1, NULL },
        [DDP_COMPONENT_PWM2]    = { MTK_DISP_PWM,       2, NULL },
-       [DDP_COMPONENT_RDMA0]   = { MTK_DISP_RDMA,      0, NULL },
-       [DDP_COMPONENT_RDMA1]   = { MTK_DISP_RDMA,      1, NULL },
-       [DDP_COMPONENT_RDMA2]   = { MTK_DISP_RDMA,      2, NULL },
+       [DDP_COMPONENT_RDMA0]   = { MTK_DISP_RDMA,      0, &ddp_rdma },
+       [DDP_COMPONENT_RDMA1]   = { MTK_DISP_RDMA,      1, &ddp_rdma },
+       [DDP_COMPONENT_RDMA2]   = { MTK_DISP_RDMA,      2, &ddp_rdma },
        [DDP_COMPONENT_UFOE]    = { MTK_DISP_UFOE,      0, &ddp_ufoe },
        [DDP_COMPONENT_WDMA0]   = { MTK_DISP_WDMA,      0, NULL },
        [DDP_COMPONENT_WDMA1]   = { MTK_DISP_WDMA,      1, NULL },
 };
 
-static bool mtk_drm_find_comp_in_ddp(struct mtk_ddp_comp ddp_comp,
+static bool mtk_drm_find_comp_in_ddp(struct device *dev,
                                     const enum mtk_ddp_comp_id *path,
-                                    unsigned int path_len)
+                                    unsigned int path_len,
+                                    struct mtk_ddp_comp *ddp_comp)
 {
        unsigned int i;
 
@@ -424,7 +407,7 @@ static bool mtk_drm_find_comp_in_ddp(struct mtk_ddp_comp ddp_comp,
                return false;
 
        for (i = 0U; i < path_len; i++)
-               if (ddp_comp.id == path[i])
+               if (dev == ddp_comp[path[i]].dev)
                        return true;
 
        return false;
@@ -446,18 +429,19 @@ int mtk_ddp_comp_get_id(struct device_node *node,
 }
 
 unsigned int mtk_drm_find_possible_crtc_by_comp(struct drm_device *drm,
-                                               struct mtk_ddp_comp ddp_comp)
+                                               struct device *dev)
 {
        struct mtk_drm_private *private = drm->dev_private;
        unsigned int ret = 0;
 
-       if (mtk_drm_find_comp_in_ddp(ddp_comp, private->data->main_path, private->data->main_len))
+       if (mtk_drm_find_comp_in_ddp(dev, private->data->main_path, private->data->main_len,
+                                    private->ddp_comp))
                ret = BIT(0);
-       else if (mtk_drm_find_comp_in_ddp(ddp_comp, private->data->ext_path,
-                                         private->data->ext_len))
+       else if (mtk_drm_find_comp_in_ddp(dev, private->data->ext_path,
+                                         private->data->ext_len, private->ddp_comp))
                ret = BIT(1);
-       else if (mtk_drm_find_comp_in_ddp(ddp_comp, private->data->third_path,
-                                         private->data->third_len))
+       else if (mtk_drm_find_comp_in_ddp(dev, private->data->third_path,
+                                         private->data->third_len, private->ddp_comp))
                ret = BIT(2);
        else
                DRM_INFO("Failed to find comp in ddp table\n");
@@ -465,59 +449,15 @@ unsigned int mtk_drm_find_possible_crtc_by_comp(struct drm_device *drm,
        return ret;
 }
 
-int mtk_ddp_comp_init(struct device *dev, struct device_node *node,
-                     struct mtk_ddp_comp *comp, enum mtk_ddp_comp_id comp_id,
-                     const struct mtk_ddp_comp_funcs *funcs)
+static int mtk_ddp_get_larb_dev(struct device_node *node, struct mtk_ddp_comp *comp,
+                               struct device *dev)
 {
-       enum mtk_ddp_comp_type type;
        struct device_node *larb_node;
        struct platform_device *larb_pdev;
-#if IS_REACHABLE(CONFIG_MTK_CMDQ)
-       struct resource res;
-       struct cmdq_client_reg cmdq_reg;
-       int ret;
-#endif
-
-       if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX)
-               return -EINVAL;
-
-       type = mtk_ddp_matches[comp_id].type;
-
-       comp->id = comp_id;
-       comp->funcs = funcs ?: mtk_ddp_matches[comp_id].funcs;
-
-       if (comp_id == DDP_COMPONENT_BLS ||
-           comp_id == DDP_COMPONENT_DPI0 ||
-           comp_id == DDP_COMPONENT_DPI1 ||
-           comp_id == DDP_COMPONENT_DSI0 ||
-           comp_id == DDP_COMPONENT_DSI1 ||
-           comp_id == DDP_COMPONENT_DSI2 ||
-           comp_id == DDP_COMPONENT_DSI3 ||
-           comp_id == DDP_COMPONENT_PWM0) {
-               comp->regs = NULL;
-               comp->clk = NULL;
-               comp->irq = 0;
-               return 0;
-       }
-
-       comp->regs = of_iomap(node, 0);
-       comp->irq = of_irq_get(node, 0);
-       comp->clk = of_clk_get(node, 0);
-       if (IS_ERR(comp->clk))
-               return PTR_ERR(comp->clk);
-
-       /* Only DMA capable components need the LARB property */
-       comp->larb_dev = NULL;
-       if (type != MTK_DISP_OVL &&
-           type != MTK_DISP_OVL_2L &&
-           type != MTK_DISP_RDMA &&
-           type != MTK_DISP_WDMA)
-               return 0;
 
        larb_node = of_parse_phandle(node, "mediatek,larb", 0);
        if (!larb_node) {
-               dev_err(dev,
-                       "Missing mediadek,larb phandle in %pOF node\n", node);
+               dev_err(dev, "Missing mediadek,larb phandle in %pOF node\n", node);
                return -EINVAL;
        }
 
@@ -528,40 +468,71 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node,
                return -EPROBE_DEFER;
        }
        of_node_put(larb_node);
-
        comp->larb_dev = &larb_pdev->dev;
 
-#if IS_REACHABLE(CONFIG_MTK_CMDQ)
-       if (of_address_to_resource(node, 0, &res) != 0) {
-               dev_err(dev, "Missing reg in %s node\n", node->full_name);
-               put_device(&larb_pdev->dev);
-               return -EINVAL;
-       }
-       comp->regs_pa = res.start;
-
-       ret = cmdq_dev_get_client_reg(dev, &cmdq_reg, 0);
-       if (ret)
-               dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
-       else
-               comp->subsys = cmdq_reg.subsys;
-#endif
        return 0;
 }
 
-int mtk_ddp_comp_register(struct drm_device *drm, struct mtk_ddp_comp *comp)
+int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp,
+                     enum mtk_ddp_comp_id comp_id)
 {
-       struct mtk_drm_private *private = drm->dev_private;
+       struct platform_device *comp_pdev;
+       enum mtk_ddp_comp_type type;
+       struct mtk_ddp_comp_dev *priv;
+       int ret;
 
-       if (private->ddp_comp[comp->id])
-               return -EBUSY;
+       if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX)
+               return -EINVAL;
 
-       private->ddp_comp[comp->id] = comp;
-       return 0;
-}
+       type = mtk_ddp_matches[comp_id].type;
 
-void mtk_ddp_comp_unregister(struct drm_device *drm, struct mtk_ddp_comp *comp)
-{
-       struct mtk_drm_private *private = drm->dev_private;
+       comp->id = comp_id;
+       comp->funcs = mtk_ddp_matches[comp_id].funcs;
+       comp_pdev = of_find_device_by_node(node);
+       if (!comp_pdev) {
+               DRM_INFO("Waiting for device %s\n", node->full_name);
+               return -EPROBE_DEFER;
+       }
+       comp->dev = &comp_pdev->dev;
 
-       private->ddp_comp[comp->id] = NULL;
+       /* Only DMA capable components need the LARB property */
+       if (type == MTK_DISP_OVL ||
+           type == MTK_DISP_OVL_2L ||
+           type == MTK_DISP_RDMA ||
+           type == MTK_DISP_WDMA) {
+               ret = mtk_ddp_get_larb_dev(node, comp, comp->dev);
+               if (ret)
+                       return ret;
+       }
+
+       if (type == MTK_DISP_BLS ||
+           type == MTK_DISP_CCORR ||
+           type == MTK_DISP_COLOR ||
+           type == MTK_DISP_GAMMA ||
+           type == MTK_DPI ||
+           type == MTK_DSI ||
+           type == MTK_DISP_OVL ||
+           type == MTK_DISP_OVL_2L ||
+           type == MTK_DISP_PWM ||
+           type == MTK_DISP_RDMA)
+               return 0;
+
+       priv = devm_kzalloc(comp->dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->regs = of_iomap(node, 0);
+       priv->clk = of_clk_get(node, 0);
+       if (IS_ERR(priv->clk))
+               return PTR_ERR(priv->clk);
+
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+       ret = cmdq_dev_get_client_reg(comp->dev, &priv->cmdq_reg, 0);
+       if (ret)
+               dev_dbg(comp->dev, "get mediatek,gce-client-reg fail!\n");
+#endif
+
+       platform_set_drvdata(comp_pdev, priv);
+
+       return 0;
 }