Commit b7243862 authored by Yannick Fertre's avatar Yannick Fertre Committed by Raphael Gallais-Pou
Browse files

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: default avatarYannick Fertre <yannick.fertre@foss.st.com>
Acked-by: default avatarYannick Fertre <yannick.fertre@foss.st.com>
Acked-by: default avatarPhilippe 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: default avatarRaphael Gallais-Pou <raphael.gallais-pou@foss.st.com>
parent d8066764
Loading
Loading
Loading
Loading
+21 −1
Original line number Diff line number Diff line
@@ -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);
+1 −0
Original line number Diff line number Diff line
@@ -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;