The MIPI DSI ip found in the RZ/G3E SoC select the video input clock
based on the DU instance actually connected using the GPO0R register.

Add this feature to the driver using `RZ_MIPI_DSI_FEATURE_GPO0R`, update
the code accordingly to manage the vclk selection.

Signed-off-by: Tommaso Merciai <[email protected]>
---
v6->v7:
 - Reworked commit without static clock selection based on DT, instead clock
   selection can be done at runtime based on the CRTC output routing, this
   reflects better the HW behavior and allows more flexible configurations.

v5->v6:
 - Moved rzg2l_mipi_dsi_link_write() into rzv2h_mipi_dsi_dphy_init()
   + comments from HW Manual.

v4->v5:
 - No changes.

v3->v4:
 - No changes.

v2->v3:
 - No changes.

v1->v2:
 - No changes.

 .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c    | 36 +++++++++++++++----
 .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h   |  3 ++
 2 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c 
b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
index 15ee402155de..19f8f19e538f 100644
--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
@@ -31,13 +31,16 @@
 #include <drm/drm_probe_helper.h>
 #include <video/mipi_display.h>
 
+#include "rzg2l_du_crtc.h"
 #include "rzg2l_mipi_dsi_regs.h"
 
 MODULE_IMPORT_NS("RZV2H_CPG");
 
 #define RZG2L_DCS_BUF_SIZE     128 /* Maximum DCS buffer size in external 
memory. */
 
+#define RZ_MIPI_DSI_MAX_INPUT  2
 #define RZ_MIPI_DSI_FEATURE_16BPP      BIT(0)
+#define RZ_MIPI_DSI_FEATURE_GPO0R      BIT(1)
 
 struct rzg2l_mipi_dsi;
 
@@ -81,13 +84,14 @@ struct rzg2l_mipi_dsi {
        struct drm_bridge bridge;
        struct drm_bridge *next_bridge;
 
-       struct clk *vclk;
+       struct clk *vclk[RZ_MIPI_DSI_MAX_INPUT];
        struct clk *lpclk;
 
        enum mipi_dsi_pixel_format format;
        unsigned int num_data_lanes;
        unsigned int lanes;
        unsigned long mode_flags;
+       u8 vclk_idx;
 
        struct rzv2h_dsi_mode_calc mode_calc;
 
@@ -543,8 +547,8 @@ static int rzg2l_dphy_conf_clks(struct rzg2l_mipi_dsi *dsi, 
unsigned long mode_f
        unsigned long vclk_rate;
        unsigned int bpp;
 
-       clk_set_rate(dsi->vclk, mode_freq * KILO);
-       vclk_rate = clk_get_rate(dsi->vclk);
+       clk_set_rate(dsi->vclk[dsi->vclk_idx], mode_freq * KILO);
+       vclk_rate = clk_get_rate(dsi->vclk[dsi->vclk_idx]);
        if (vclk_rate != mode_freq * KILO)
                dev_dbg(dsi->dev, "Requested vclk rate %lu, actual %lu 
mismatch\n",
                        mode_freq * KILO, vclk_rate);
@@ -687,6 +691,19 @@ static int rzv2h_mipi_dsi_dphy_init(struct rzg2l_mipi_dsi 
*dsi,
        rzg2l_mipi_dsi_phy_write(dsi, PLLCLKSET1R,
                                 FIELD_PREP(PLLCLKSET1R_PLL_K, 
dsi_parameters->k));
 
+       /*
+        * From RZ/G3E HW manual (Rev.1.15) section 9.5.3 Operation,
+        * 9.5.3.1 Power on Reset and Initial Settings for All Operations.
+        * Figure 9.5-4 Power On/Off Sequence show that after writing to
+        * GPO0R.VICH register we need to wait for more than 1 x tp before
+        * writing to PLLENR.PLLEN.
+        *
+        * Note: GPO0R is a link register, not a PHY register. This setting
+        * is specific to RZ/G3E.
+        */
+       if (dsi->info->features & RZ_MIPI_DSI_FEATURE_GPO0R)
+               rzg2l_mipi_dsi_link_write(dsi, GPO0R, dsi->vclk_idx);
+
        /*
         * From RZ/V2H HW manual (Rev.1.20) section 9.5.3 Operation,
         * (C) After write to D-PHY registers we need to wait for more than 1 x 
tp
@@ -1031,6 +1048,7 @@ static void rzg2l_mipi_dsi_atomic_pre_enable(struct 
drm_bridge *bridge,
        crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
        mode = &drm_atomic_get_new_crtc_state(state, crtc)->adjusted_mode;
 
+       dsi->vclk_idx = to_rzg2l_crtc(crtc)->hw_index;
        rzg2l_mipi_dsi_startup(dsi, mode);
 }
 
@@ -1425,9 +1443,15 @@ static int rzg2l_mipi_dsi_probe(struct platform_device 
*pdev)
        if (IS_ERR(dsi->mmio))
                return PTR_ERR(dsi->mmio);
 
-       dsi->vclk = devm_clk_get(dsi->dev, "vclk");
-       if (IS_ERR(dsi->vclk))
-               return PTR_ERR(dsi->vclk);
+       dsi->vclk[0] = devm_clk_get(dsi->dev, "vclk");
+       if (IS_ERR(dsi->vclk[0]))
+               return PTR_ERR(dsi->vclk[0]);
+
+       if (dsi->info->features & RZ_MIPI_DSI_FEATURE_GPO0R) {
+               dsi->vclk[1] = devm_clk_get(dsi->dev, "vclk2");
+               if (IS_ERR(dsi->vclk[1]))
+                       return PTR_ERR(dsi->vclk[1]);
+       }
 
        dsi->lpclk = devm_clk_get(dsi->dev, "lpclk");
        if (IS_ERR(dsi->lpclk))
diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h 
b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h
index 2bef20566648..cee2e0bc5dc5 100644
--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h
@@ -83,6 +83,9 @@
 #define LINKSR_SQCHRUN1                        BIT(4)
 #define LINKSR_SQCHRUN0                        BIT(0)
 
+/* RZ/G3E General Purpose Output 0 Register */
+#define GPO0R                          0xc0
+
 /* Tx Set Register */
 #define TXSETR                         0x100
 #define TXSETR_NUMLANECAP              (0x3 << 16)
-- 
2.54.0

Reply via email to