Add the Rockchip-sepcific dual-dsi setup and hook it into the VOP as well.
As described in the general dual-dsi devicetree binding, the panel should
define two input ports and point each of them to one of the used dsi-
controllers, as well as declare one of them as clock-master.
This is used to determine the dual-dsi state and get access to both
controller instances.

Signed-off-by: Heiko Stuebner <he...@sntech.de>
---
 .../gpu/drm/rockchip/dw-mipi-dsi-rockchip.c   | 67 ++++++++++++++++++-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h   |  1 +
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c   |  3 +
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h   |  4 ++
 drivers/gpu/drm/rockchip/rockchip_vop_reg.c   |  1 +
 5 files changed, 75 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c 
b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
index 93b019482276..cc47610d5bdf 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
@@ -227,6 +227,10 @@ struct dw_mipi_dsi_rockchip {
        struct clk *grf_clk;
        struct clk *phy_cfg_clk;
 
+       /* dual-channel */
+       bool is_slave;
+       struct dw_mipi_dsi_rockchip *slave;
+
        unsigned int lane_mbps; /* per lane */
        u16 input_div;
        u16 feedback_div;
@@ -613,6 +617,8 @@ static void dw_mipi_dsi_encoder_mode_set(struct drm_encoder 
*encoder,
        }
 
        dw_mipi_dsi_rockchip_config(dsi, mux);
+       if (dsi->slave)
+               dw_mipi_dsi_rockchip_config(dsi->slave, mux);
 
        clk_disable_unprepare(dsi->grf_clk);
 }
@@ -641,6 +647,8 @@ dw_mipi_dsi_encoder_atomic_check(struct drm_encoder 
*encoder,
        }
 
        s->output_type = DRM_MODE_CONNECTOR_DSI;
+       if (dsi->slave)
+               s->output_flags = ROCKCHIP_OUTPUT_DSI_DUAL;
 
        return 0;
 }
@@ -650,6 +658,8 @@ static void dw_mipi_dsi_encoder_disable(struct drm_encoder 
*encoder)
        struct dw_mipi_dsi_rockchip *dsi = to_dsi(encoder);
 
        pm_runtime_put(dsi->dev);
+       if (dsi->slave)
+               pm_runtime_put(dsi->slave->dev);
 }
 
 static const struct drm_encoder_helper_funcs
@@ -690,18 +700,70 @@ static int dw_mipi_dsi_rockchip_bind(struct device *dev,
 {
        struct dw_mipi_dsi_rockchip *dsi = dev_get_drvdata(dev);
        struct drm_device *drm_dev = data;
+       struct device_node *second_np;
        struct drm_bridge *bridge;
        struct drm_panel *panel;
+       bool master1, master2;
        int ret;
 
        /*
-        * Handle probe-deferrals due to missing display.
+        * At this point both DSIs (if in use) should have probed and found
+        * any connected displays or bridges.
+        * This also takes care of handling possible probe-deferrals.
         */
        ret = drm_of_find_panel_or_bridge(dsi->dev->of_node, 1, 0,
                                          &panel, &bridge);
        if (ret)
                return ret;
 
+       second_np = of_mipi_dsi_find_second_host(dsi->dev->of_node, 1, 0);
+       if (IS_ERR(second_np))
+               return PTR_ERR(second_np);
+
+       if (second_np) {
+               struct platform_device *pdev;
+
+               master1 = of_property_read_bool(dsi->dev->of_node,
+                                               "clock-master");
+               master2 = of_property_read_bool(second_np, "clock-master");
+
+               if (master1 && master2) {
+                       DRM_DEV_ERROR(dsi->dev, "only one clock-master 
allowed\n");
+                       of_node_put(second_np);
+                       return -EINVAL;
+               }
+
+               if (!master1 && !master2) {
+                       DRM_DEV_ERROR(dsi->dev, "no clock-master defined\n");
+                       of_node_put(second_np);
+                       return -EINVAL;
+               }
+
+               /* we are the slave in dual-DSI */
+               if (!master1) {
+                       dsi->is_slave = true;
+                       of_node_put(second_np);
+                       return 0;
+               }
+
+               pdev = of_find_device_by_node(second_np);
+               if (!pdev) {
+                       DRM_DEV_ERROR(dev, "could not find slave controller\n");
+                       return -ENODEV;
+               }
+
+               dsi->slave = platform_get_drvdata(pdev);
+               if (!dsi->slave) {
+                       DRM_DEV_ERROR(dev, "could not get slaves 
platform-data\n");
+                       return -ENODEV;
+               }
+
+               dsi->slave->is_slave = true;
+               dw_mipi_dsi_set_slave(dsi->dmd, dsi->slave->dmd);
+
+               of_node_put(second_np);
+       }
+
        ret = rockchip_dsi_drm_create_encoder(dsi, drm_dev);
        if (ret) {
                DRM_DEV_ERROR(dev, "Failed to create drm encoder\n");
@@ -723,6 +785,9 @@ static void dw_mipi_dsi_rockchip_unbind(struct device *dev,
 {
        struct dw_mipi_dsi_rockchip *dsi = dev_get_drvdata(dev);
 
+       if (dsi->is_slave)
+               return;
+
        dw_mipi_dsi_unbind(dsi->dmd);
 }
 
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 3013992d088d..f8861ba3c025 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -36,6 +36,7 @@ struct rockchip_crtc_state {
        struct drm_crtc_state base;
        int output_type;
        int output_mode;
+       int output_flags;
 };
 #define to_rockchip_crtc_state(s) \
                container_of(s, struct rockchip_crtc_state, base)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 7192e101bb44..2f6eac7ed510 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -905,6 +905,7 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc,
        pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) ?
                   BIT(VSYNC_POSITIVE) : 0;
        VOP_REG_SET(vop, output, pin_pol, pin_pol);
+       VOP_REG_SET(vop, output, mipi_dual_channel_en, 0);
 
        switch (s->output_type) {
        case DRM_MODE_CONNECTOR_LVDS:
@@ -922,6 +923,8 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc,
        case DRM_MODE_CONNECTOR_DSI:
                VOP_REG_SET(vop, output, mipi_pin_pol, pin_pol);
                VOP_REG_SET(vop, output, mipi_en, 1);
+               VOP_REG_SET(vop, output, mipi_dual_channel_en,
+                           !!(s->output_flags & ROCKCHIP_OUTPUT_DSI_DUAL));
                break;
        case DRM_MODE_CONNECTOR_DisplayPort:
                pin_pol &= ~BIT(DCLK_INVERT);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
index 56bbd2e2a8ef..a4627d2343a3 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
@@ -60,6 +60,7 @@ struct vop_output {
        struct vop_reg edp_en;
        struct vop_reg hdmi_en;
        struct vop_reg mipi_en;
+       struct vop_reg mipi_dual_channel_en;
        struct vop_reg rgb_en;
 };
 
@@ -212,6 +213,9 @@ struct vop_data {
 /* for use special outface */
 #define ROCKCHIP_OUT_MODE_AAAA 15
 
+/* output flags */
+#define ROCKCHIP_OUTPUT_DSI_DUAL       BIT(0)
+
 enum alpha_mode {
        ALPHA_STRAIGHT,
        ALPHA_INVERSE,
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c 
b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
index 2e4eea3459fe..7d294290ef11 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
@@ -420,6 +420,7 @@ static const struct vop_output rk3399_output = {
        .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
        .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
        .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
+       .mipi_dual_channel_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 3),
 };
 
 static const struct vop_data rk3399_vop_big = {
-- 
2.17.0

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

Reply via email to