From c2af9b24bfa69ffb12e72153f89ed3bb3245fafb Mon Sep 17 00:00:00 2001
From: Laurentiu Palcu <laurentiu.palcu@nxp.com>
Date: Fri, 22 Nov 2019 10:00:56 +0200
Subject: [PATCH 40/49] drm/imx/dcss: use the external 27MHz phy clock

The 27MHz external oscillator offers a high precision low jitter clock and
is suitable for high pixel clocks modes(ie 4K@60).

Signed-off-by: Laurentiu Palcu <laurentiu.palcu@nxp.com>
---
 drivers/gpu/drm/imx/dcss/dcss-dev.c | 25 +++++++++++++++++++------
 drivers/gpu/drm/imx/dcss/dcss-dtg.c | 11 +++++++++++
 2 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/imx/dcss/dcss-dev.c b/drivers/gpu/drm/imx/dcss/dcss-dev.c
index c849533ca83e..1977f6b058f8 100644
--- a/drivers/gpu/drm/imx/dcss/dcss-dev.c
+++ b/drivers/gpu/drm/imx/dcss/dcss-dev.c
@@ -17,6 +17,11 @@
 
 static void dcss_clocks_enable(struct dcss_dev *dcss)
 {
+	if (dcss->hdmi_output) {
+		clk_prepare_enable(dcss->pll_phy_ref_clk);
+		clk_prepare_enable(dcss->pll_src_clk);
+	}
+
 	clk_prepare_enable(dcss->axi_clk);
 	clk_prepare_enable(dcss->apb_clk);
 	clk_prepare_enable(dcss->rtrm_clk);
@@ -31,6 +36,11 @@ static void dcss_clocks_disable(struct dcss_dev *dcss)
 	clk_disable_unprepare(dcss->rtrm_clk);
 	clk_disable_unprepare(dcss->apb_clk);
 	clk_disable_unprepare(dcss->axi_clk);
+
+	if (dcss->hdmi_output) {
+		clk_disable_unprepare(dcss->pll_src_clk);
+		clk_disable_unprepare(dcss->pll_phy_ref_clk);
+	}
 }
 
 static void dcss_disable_dtg_and_ss_cb(void *data)
@@ -133,17 +143,20 @@ static int dcss_clks_init(struct dcss_dev *dcss)
 	struct {
 		const char *id;
 		struct clk **clk;
+		bool required;
 	} clks[] = {
-		{"apb",   &dcss->apb_clk},
-		{"axi",   &dcss->axi_clk},
-		{"pix",   &dcss->pix_clk},
-		{"rtrm",  &dcss->rtrm_clk},
-		{"dtrc",  &dcss->dtrc_clk},
+		{"apb",   &dcss->apb_clk, true},
+		{"axi",   &dcss->axi_clk, true},
+		{"pix",   &dcss->pix_clk, true},
+		{"rtrm",  &dcss->rtrm_clk, true},
+		{"dtrc",  &dcss->dtrc_clk, true},
+		{"pll_src",  &dcss->pll_src_clk, dcss->hdmi_output},
+		{"pll_phy_ref",  &dcss->pll_phy_ref_clk, dcss->hdmi_output},
 	};
 
 	for (i = 0; i < ARRAY_SIZE(clks); i++) {
 		*clks[i].clk = devm_clk_get(dcss->dev, clks[i].id);
-		if (IS_ERR(*clks[i].clk)) {
+		if (IS_ERR(*clks[i].clk) && clks[i].required) {
 			dev_err(dcss->dev, "failed to get %s clock\n",
 				clks[i].id);
 			return PTR_ERR(*clks[i].clk);
diff --git a/drivers/gpu/drm/imx/dcss/dcss-dtg.c b/drivers/gpu/drm/imx/dcss/dcss-dtg.c
index 30de00540f63..b70785d69ad9 100644
--- a/drivers/gpu/drm/imx/dcss/dcss-dtg.c
+++ b/drivers/gpu/drm/imx/dcss/dcss-dtg.c
@@ -83,6 +83,7 @@ struct dcss_dtg {
 	u32 ctx_id;
 
 	bool in_use;
+	bool hdmi_output;
 
 	u32 dis_ulc_x;
 	u32 dis_ulc_y;
@@ -159,6 +160,7 @@ int dcss_dtg_init(struct dcss_dev *dcss, unsigned long dtg_base)
 	dcss->dtg = dtg;
 	dtg->dev = dcss->dev;
 	dtg->ctxld = dcss->ctxld;
+	dtg->hdmi_output = dcss->hdmi_output;
 
 	dtg->base_reg = ioremap(dtg_base, SZ_4K);
 	if (!dtg->base_reg) {
@@ -221,6 +223,15 @@ void dcss_dtg_sync_set(struct dcss_dtg *dtg, struct videomode *vm)
 		    vm->vactive - 1;
 
 	clk_disable_unprepare(dcss->pix_clk);
+	if (dcss->hdmi_output) {
+		int err;
+
+		clk_disable_unprepare(dcss->pll_src_clk);
+		err = clk_set_parent(dcss->pll_src_clk, dcss->pll_phy_ref_clk);
+		if (err < 0)
+			dev_warn(dcss->dev, "clk_set_parent() returned %d", err);
+		clk_prepare_enable(dcss->pll_src_clk);
+	}
 	clk_set_rate(dcss->pix_clk, vm->pixelclock);
 	clk_prepare_enable(dcss->pix_clk);
 
-- 
2.29.2

