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
