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 with the introduction of `rzg2l_mipi_dsi_get_input_port()`. Signed-off-by: Tommaso Merciai <[email protected]> --- .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c | 67 +++++++++++++++++-- .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h | 3 + 2 files changed, 64 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 ccc2758bafb0..59125460cf57 100644 --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c @@ -37,7 +37,9 @@ 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 +83,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; @@ -552,8 +555,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); @@ -764,6 +767,11 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi, if (ret < 0) goto err_phy; + if (dsi->info->features & RZ_MIPI_DSI_FEATURE_GPO0R) + rzg2l_mipi_dsi_link_write(dsi, GPO0R, dsi->vclk_idx); + + dev_dbg(dsi->dev, "selected du%d input channel\n", dsi->vclk_idx); + /* Enable Data lanes and Clock lanes */ txsetr = TXSETR_DLEN | TXSETR_NUMLANEUSE(dsi->lanes - 1) | TXSETR_CLEN; rzg2l_mipi_dsi_link_write(dsi, TXSETR, txsetr); @@ -1006,6 +1014,37 @@ static int rzg2l_mipi_dsi_stop_video(struct rzg2l_mipi_dsi *dsi) return ret; } +static int rzg2l_mipi_dsi_get_input_port(struct rzg2l_mipi_dsi *dsi) +{ + struct device_node *np = dsi->dev->of_node; + struct device_node *remote_ep, *ep_node; + struct of_endpoint ep; + bool ep_enabled; + int in_port; + + /* DSI can have only one port enabled */ + for_each_endpoint_of_node(np, ep_node) { + of_graph_parse_endpoint(ep_node, &ep); + if (ep.port >= RZ_MIPI_DSI_MAX_INPUT) + break; + + remote_ep = of_graph_get_remote_endpoint(ep_node); + ep_enabled = of_device_is_available(remote_ep); + of_node_put(remote_ep); + + if (ep_enabled) { + in_port = ep.port; + break; + } + } + + if (!ep_enabled) + return -EINVAL; + + dev_dbg(dsi->dev, "input port@%d\n", in_port); + return in_port; +} + /* ----------------------------------------------------------------------------- * Bridge */ @@ -1400,9 +1439,25 @@ 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); + if (dsi->info->features & RZ_MIPI_DSI_FEATURE_GPO0R) { + dsi->vclk[0] = devm_clk_get(dsi->dev, "vclk1"); + if (IS_ERR(dsi->vclk[0])) + return PTR_ERR(dsi->vclk[0]); + + dsi->vclk[1] = devm_clk_get(dsi->dev, "vclk2"); + if (IS_ERR(dsi->vclk[1])) + return PTR_ERR(dsi->vclk[1]); + + ret = rzg2l_mipi_dsi_get_input_port(dsi); + if (ret < 0) + return dev_err_probe(dsi->dev, -EINVAL, + "No available input port\n"); + dsi->vclk_idx = ret; + } else { + dsi->vclk[0] = devm_clk_get(dsi->dev, "vclk"); + if (IS_ERR(dsi->vclk[0])) + return PTR_ERR(dsi->vclk[0]); + } 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.43.0
