Hi Prabhakar, Thanks for the patch. > -----Original Message----- > From: Prabhakar <prabhakar.csengg@xxxxxxxxx> > Sent: 30 April 2025 21:41 > Subject: [PATCH v4 13/15] drm: renesas: rz-du: mipi_dsi: Add function pointers for configuring VCLK > and mode validation > > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx> > > Introduce `dphy_conf_clks` and `dphy_mode_clk_check` callbacks in `rzg2l_mipi_dsi_hw_info` to > configure the VCLK and validate supported display modes. > > On the RZ/V2H(P) SoC, the DSI PLL dividers need to be as accurate as possible. To ensure compatibility > with both RZ/G2L and RZ/V2H(P) SoCs, function pointers are introduced. > > Modify `rzg2l_mipi_dsi_startup()` to use `dphy_conf_clks` for clock configuration and > `rzg2l_mipi_dsi_bridge_mode_valid()` to invoke `dphy_mode_clk_check` for mode validation. > > This change ensures proper operation across different SoC variants by allowing fine-grained control > over clock configuration and mode validation. > > Co-developed-by: Fabrizio Castro <fabrizio.castro.jz@xxxxxxxxxxx> > Signed-off-by: Fabrizio Castro <fabrizio.castro.jz@xxxxxxxxxxx> > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx> Reviewed-by: Biju Das <biju.das.jz@xxxxxxxxxxxxxx> Cheers, Biju > --- > v3->v4: > - Replaced KILO with MILLI > > v2->v3: > - Replaced unsigned long long with u64 > > v1->v2: > - No changes > --- > .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c | 59 +++++++++++++------ > 1 file changed, 42 insertions(+), 17 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 66eef39af35e..df43ff59e08e 100644 > --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c > +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c > @@ -37,6 +37,10 @@ struct rzg2l_mipi_dsi_hw_info { > int (*dphy_init)(struct rzg2l_mipi_dsi *dsi, u64 hsfreq_millihz); > void (*dphy_late_init)(struct rzg2l_mipi_dsi *dsi); > void (*dphy_exit)(struct rzg2l_mipi_dsi *dsi); > + int (*dphy_conf_clks)(struct rzg2l_mipi_dsi *dsi, unsigned long mode_freq, > + u64 *hsfreq_millihz); > + unsigned int (*dphy_mode_clk_check)(struct rzg2l_mipi_dsi *dsi, > + unsigned long mode_freq); > u32 phy_reg_offset; > u32 link_reg_offset; > unsigned long max_dclk; > @@ -276,12 +280,36 @@ static void rzg2l_mipi_dsi_dphy_exit(struct rzg2l_mipi_dsi *dsi) > reset_control_assert(dsi->rstc); > } > > +static int rzg2l_dphy_conf_clks(struct rzg2l_mipi_dsi *dsi, unsigned long mode_freq, > + u64 *hsfreq_millihz) > +{ > + unsigned long vclk_rate; > + unsigned int bpp; > + > + clk_set_rate(dsi->vclk, mode_freq * MILLI); > + /* > + * Relationship between hsclk and vclk must follow > + * vclk * bpp = hsclk * 8 * lanes > + * where vclk: video clock (Hz) > + * bpp: video pixel bit depth > + * hsclk: DSI HS Byte clock frequency (Hz) > + * lanes: number of data lanes > + * > + * hsclk(bit) = hsclk(byte) * 8 = hsfreq > + */ > + bpp = mipi_dsi_pixel_format_to_bpp(dsi->format); > + vclk_rate = clk_get_rate(dsi->vclk); > + *hsfreq_millihz = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(vclk_rate, bpp * MILLI), > + dsi->lanes); > + > + return 0; > +} > + > static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi, > const struct drm_display_mode *mode) { > - unsigned long hsfreq, vclk_rate; > + unsigned long hsfreq; > u64 hsfreq_millihz; > - unsigned int bpp; > u32 txsetr; > u32 clstptsetr; > u32 lptrnstsetr; > @@ -295,21 +323,9 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi, > if (ret < 0) > return ret; > > - clk_set_rate(dsi->vclk, mode->clock * MILLI); > - > - /* > - * Relationship between hsclk and vclk must follow > - * vclk * bpp = hsclk * 8 * lanes > - * where vclk: video clock (Hz) > - * bpp: video pixel bit depth > - * hsclk: DSI HS Byte clock frequency (Hz) > - * lanes: number of data lanes > - * > - * hsclk(bit) = hsclk(byte) * 8 = hsfreq > - */ > - bpp = mipi_dsi_pixel_format_to_bpp(dsi->format); > - vclk_rate = clk_get_rate(dsi->vclk); > - hsfreq_millihz = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(vclk_rate, bpp * MILLI), dsi->lanes); > + ret = dsi->info->dphy_conf_clks(dsi, mode->clock, &hsfreq_millihz); > + if (ret < 0) > + goto err_phy; > > ret = dsi->info->dphy_init(dsi, hsfreq_millihz); > if (ret < 0) > @@ -616,6 +632,14 @@ rzg2l_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge, > if (mode->clock < dsi->info->min_dclk) > return MODE_CLOCK_LOW; > > + if (dsi->info->dphy_mode_clk_check) { > + enum drm_mode_status status; > + > + status = dsi->info->dphy_mode_clk_check(dsi, mode->clock); > + if (status != MODE_OK) > + return status; > + } > + > return MODE_OK; > } > > @@ -835,6 +859,7 @@ static void rzg2l_mipi_dsi_remove(struct platform_device *pdev) static const > struct rzg2l_mipi_dsi_hw_info rzg2l_mipi_dsi_info = { > .dphy_init = rzg2l_mipi_dsi_dphy_init, > .dphy_exit = rzg2l_mipi_dsi_dphy_exit, > + .dphy_conf_clks = rzg2l_dphy_conf_clks, > .link_reg_offset = 0x10000, > .max_dclk = 148500, > .min_dclk = 5803, > -- > 2.49.0