diff options
| author | Yannick Fertre <yannick.fertre@foss.st.com> | 2025-08-22 16:34:17 +0200 |
|---|---|---|
| committer | Raphael Gallais-Pou <raphael.gallais-pou@foss.st.com> | 2025-08-28 17:43:57 +0200 |
| commit | b7243862f82a088d6fb7e22a25c7c024818e631d (patch) | |
| tree | 256f491b7b5201e3b7655bbe56c5c56f8b8ab59f | |
| parent | d80667642b0f43580efd489d627dd24aa10ab98f (diff) | |
drm/stm: ltdc: handle lvds pixel clock
Handle LVDS pixel clock.
The LTDC operates with multiple clock domains for register access,
requiring all clocks to be provided during read/write operations. This
imposes a dependency between the LVDS and LTDC to access correctly all
LTDC registers. And because both IPs' pixel rates must be synchronized,
the LTDC has to handle the LVDS clock.
Signed-off-by: Yannick Fertre <yannick.fertre@foss.st.com>
Acked-by: Yannick Fertre <yannick.fertre@foss.st.com>
Acked-by: Philippe Cornu <philippe.cornu@foss.st.com>
Link: https://lore.kernel.org/r/20250822-drm-misc-next-v5-8-9c825e28f733@foss.st.com
Signed-off-by: Raphael Gallais-Pou <raphael.gallais-pou@foss.st.com>
| -rw-r--r-- | drivers/gpu/drm/stm/ltdc.c | 22 | ||||
| -rw-r--r-- | drivers/gpu/drm/stm/ltdc.h | 1 |
2 files changed, 22 insertions, 1 deletions
diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index 9970bcb748ea..d1501e86a5b1 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -838,6 +838,12 @@ ltdc_crtc_mode_valid(struct drm_crtc *crtc, int target_max = target + CLK_TOLERANCE_HZ; int result; + if (ldev->lvds_clk) { + result = clk_round_rate(ldev->lvds_clk, target); + drm_dbg_driver(crtc->dev, "lvds pixclk rate target %d, available %d\n", + target, result); + } + result = clk_round_rate(ldev->pixel_clk, target); drm_dbg_driver(crtc->dev, "clk rate target %d, available %d\n", target, result); @@ -1879,6 +1885,8 @@ void ltdc_suspend(struct drm_device *ddev) clk_disable_unprepare(ldev->pixel_clk); if (ldev->bus_clk) clk_disable_unprepare(ldev->bus_clk); + if (ldev->lvds_clk) + clk_disable_unprepare(ldev->lvds_clk); } int ltdc_resume(struct drm_device *ddev) @@ -1896,8 +1904,16 @@ int ltdc_resume(struct drm_device *ddev) if (ldev->bus_clk) { ret = clk_prepare_enable(ldev->bus_clk); - if (ret) + if (ret) { drm_err(ddev, "failed to enable bus clock (%d)\n", ret); + return ret; + } + } + + if (ldev->lvds_clk) { + ret = clk_prepare_enable(ldev->lvds_clk); + if (ret) + drm_err(ddev, "failed to prepare lvds clock\n"); } return ret; @@ -1982,6 +1998,10 @@ int ltdc_load(struct drm_device *ddev) } } + ldev->lvds_clk = devm_clk_get(dev, "lvds"); + if (IS_ERR(ldev->lvds_clk)) + ldev->lvds_clk = NULL; + rstc = devm_reset_control_get_exclusive(dev, NULL); mutex_init(&ldev->err_lock); diff --git a/drivers/gpu/drm/stm/ltdc.h b/drivers/gpu/drm/stm/ltdc.h index ddfa8ae61a7b..17b51a7ce28e 100644 --- a/drivers/gpu/drm/stm/ltdc.h +++ b/drivers/gpu/drm/stm/ltdc.h @@ -48,6 +48,7 @@ struct ltdc_device { void __iomem *regs; struct regmap *regmap; struct clk *pixel_clk; /* lcd pixel clock */ + struct clk *lvds_clk; /* lvds pixel clock */ struct clk *bus_clk; /* bus clock */ struct mutex err_lock; /* protecting error_status */ struct ltdc_caps caps; |