Skip to contentSkip to conversation

ARM: imx6q: clk: Parent DI clocks to video PLL via di_pre_sel

PATCH New Philipp Zabel 5 participants 7 messages Apr 14, 2014 – Apr 23, 2014

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/2 ARM: imx6q: clk: Parent DI clocks to video PLL via di_pre_sel

From: Sascha Hauer <[email protected]>

Route the video PLL to the display interface clocks via the di_pre_sel and di_sel muxes by default.

---
 arch/arm/mach-imx/clk-imx6q.c | 9 +++++++++
 1 file changed, 9 insertions(+)
arch/arm/mach-imx/clk-imx6q.c +9 -0
index a3a69ab..ba17299 100644
@@ -445,6 +445,15 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 		clk_set_parent(clk[ldb_di1_sel], clk[pll5_video_div]);
 	}
 
+	clk_set_parent(clk[ipu1_di0_pre_sel], clk[pll5_video_div]);
+	clk_set_parent(clk[ipu1_di1_pre_sel], clk[pll5_video_div]);
+	clk_set_parent(clk[ipu2_di0_pre_sel], clk[pll5_video_div]);
+	clk_set_parent(clk[ipu2_di1_pre_sel], clk[pll5_video_div]);
+	clk_set_parent(clk[ipu1_di0_sel], clk[ipu1_di0_pre]);
+	clk_set_parent(clk[ipu1_di1_sel], clk[ipu1_di1_pre]);
+	clk_set_parent(clk[ipu2_di0_sel], clk[ipu2_di0_pre]);
+	clk_set_parent(clk[ipu2_di1_sel], clk[ipu2_di1_pre]);
+
 	/*
 	 * The gpmi needs 100MHz frequency in the EDO/Sync mode,
 	 * We can not get the 100MHz from the pll2_pfd0_352m.
Signature · 1 line
1.9.1
#1 lore raw

PATCH 2/2 ARM: i.MX6: ipu_di_sel clocks can set parent rates

To obtain exact pixel clocks, allow the DI clock selectors to influence the PLLs that they are derived from.

---
 arch/arm/mach-imx/clk-imx6q.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)
arch/arm/mach-imx/clk-imx6q.c +8 -8
index ba17299..c8fb227 100644
@@ -258,14 +258,14 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 	clk[ipu2_sel]         = imx_clk_mux("ipu2_sel",         base + 0x3c, 14, 2, ipu_sels,          ARRAY_SIZE(ipu_sels));
 	clk[ldb_di0_sel]      = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9,  3, ldb_di_sels,      ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
 	clk[ldb_di1_sel]      = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels,      ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
-	clk[ipu1_di0_pre_sel] = imx_clk_mux("ipu1_di0_pre_sel", base + 0x34, 6,  3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels));
-	clk[ipu1_di1_pre_sel] = imx_clk_mux("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels));
-	clk[ipu2_di0_pre_sel] = imx_clk_mux("ipu2_di0_pre_sel", base + 0x38, 6,  3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels));
-	clk[ipu2_di1_pre_sel] = imx_clk_mux("ipu2_di1_pre_sel", base + 0x38, 15, 3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels));
-	clk[ipu1_di0_sel]     = imx_clk_mux("ipu1_di0_sel",     base + 0x34, 0,  3, ipu1_di0_sels,     ARRAY_SIZE(ipu1_di0_sels));
-	clk[ipu1_di1_sel]     = imx_clk_mux("ipu1_di1_sel",     base + 0x34, 9,  3, ipu1_di1_sels,     ARRAY_SIZE(ipu1_di1_sels));
-	clk[ipu2_di0_sel]     = imx_clk_mux("ipu2_di0_sel",     base + 0x38, 0,  3, ipu2_di0_sels,     ARRAY_SIZE(ipu2_di0_sels));
-	clk[ipu2_di1_sel]     = imx_clk_mux("ipu2_di1_sel",     base + 0x38, 9,  3, ipu2_di1_sels,     ARRAY_SIZE(ipu2_di1_sels));
+	clk[ipu1_di0_pre_sel] = imx_clk_mux_flags("ipu1_di0_pre_sel", base + 0x34, 6,  3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
+	clk[ipu1_di1_pre_sel] = imx_clk_mux_flags("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
+	clk[ipu2_di0_pre_sel] = imx_clk_mux_flags("ipu2_di0_pre_sel", base + 0x38, 6,  3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
+	clk[ipu2_di1_pre_sel] = imx_clk_mux_flags("ipu2_di1_pre_sel", base + 0x38, 15, 3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
+	clk[ipu1_di0_sel]     = imx_clk_mux_flags("ipu1_di0_sel",     base + 0x34, 0,  3, ipu1_di0_sels,     ARRAY_SIZE(ipu1_di0_sels), CLK_SET_RATE_PARENT);
+	clk[ipu1_di1_sel]     = imx_clk_mux_flags("ipu1_di1_sel",     base + 0x34, 9,  3, ipu1_di1_sels,     ARRAY_SIZE(ipu1_di1_sels), CLK_SET_RATE_PARENT);
+	clk[ipu2_di0_sel]     = imx_clk_mux_flags("ipu2_di0_sel",     base + 0x38, 0,  3, ipu2_di0_sels,     ARRAY_SIZE(ipu2_di0_sels), CLK_SET_RATE_PARENT);
+	clk[ipu2_di1_sel]     = imx_clk_mux_flags("ipu2_di1_sel",     base + 0x38, 9,  3, ipu2_di1_sels,     ARRAY_SIZE(ipu2_di1_sels), CLK_SET_RATE_PARENT);
 	clk[hsi_tx_sel]       = imx_clk_mux("hsi_tx_sel",       base + 0x30, 28, 1, hsi_tx_sels,       ARRAY_SIZE(hsi_tx_sels));
 	clk[pcie_axi_sel]     = imx_clk_mux("pcie_axi_sel",     base + 0x18, 10, 1, pcie_axi_sels,     ARRAY_SIZE(pcie_axi_sels));
 	clk[ssi1_sel]         = imx_clk_fixup_mux("ssi1_sel",   base + 0x1c, 10, 2, ssi_sels,          ARRAY_SIZE(ssi_sels),          imx_cscmr1_fixup);
Signature · 1 line
1.9.1
#2 lore raw

PATCH 2/2 ARM: i.MX6: ipu_di_sel clocks can set parent rates

Quoted 4 lines · Philipp Zabel

To obtain exact pixel clocks, allow the DI clock selectors to influence the PLLs that they are derived from.

Both these appear to work for me on the iMX6Solo Hummingboard, and fix the ability of imx-hdmi to produce a picture with correct timing. So...

For reference, at 1080p, I see:

    pll5_video                  1           1            1188000000 0
       pll5_post_div            1           1            297000000  0
          pll5_video_div        1           1            148500000  0
...
             ipu1_di0_pre_sel   1           1            148500000  0
                ipu1_di0_pre    1           1            148500000  0
                   ipu1_di0_sel 1           1            148500000  0
                      ipu1_di0  1           1            148500000  0
Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
#4 lore raw

PATCH 1/2 ARM: imx6q: clk: Parent DI clocks to video PLL via di_pre_sel

In reply to Philipp Zabel
Quoted 21 lines · Philipp Zabel

From: Sascha Hauer <[email protected]>

Route the video PLL to the display interface clocks via the di_pre_sel and di_sel muxes by default.

---
  arch/arm/mach-imx/clk-imx6q.c | 9 +++++++++
  1 file changed, 9 insertions(+)
arch/arm/mach-imx/clk-imx6q.c +2 -0
index a3a69ab..ba17299 100644
@@ -445,6 +445,15 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
  		clk_set_parent(clk[ldb_di1_sel], clk[pll5_video_div]);
  	}
 
+	clk_set_parent(clk[ipu1_di0_pre_sel], clk[pll5_video_div]);
+	clk_set_parent(clk[ipu1_di1_pre_sel], clk[pll5_video_div]);

arch/arm/mach-imx/clk-imx6q.c static void __init imx6q_clocks_init(struct device_node *ccm_node) · line 459

Quoted 10 lines
arch/arm/mach-imx/clk-imx6q.c +7 -0
+	clk_set_parent(clk[ipu2_di0_pre_sel], clk[pll5_video_div]);
+	clk_set_parent(clk[ipu2_di1_pre_sel], clk[pll5_video_div]);
+	clk_set_parent(clk[ipu1_di0_sel], clk[ipu1_di0_pre]);
+	clk_set_parent(clk[ipu1_di1_sel], clk[ipu1_di1_pre]);
+	clk_set_parent(clk[ipu2_di0_sel], clk[ipu2_di0_pre]);
+	clk_set_parent(clk[ipu2_di1_sel], clk[ipu2_di1_pre]);
+
  	/*
  	 * The gpmi needs 100MHz frequency in the EDO/Sync mode,
  	 * We can not get the 100MHz from the pll2_pfd0_352m.

I'm no expert on this, so just a question from an internal review:

With this, having both ldb_di0_sel and ipu1_di0_sel driven by pll5_video, what will happen if both lvds and hdmi are trying to set the rate of pll5_video_div?

Best regards

Dirk

#5 lore raw

PATCH 1/2 ARM: imx6q: clk: Parent DI clocks to video PLL via di_pre_sel

Am Mittwoch, den 23.04.2014, 09:55 +0200 schrieb Dirk Behme:

Quoted 35 lines · Philipp Zabel
Quoted 21 lines

From: Sascha Hauer <[email protected]>

Route the video PLL to the display interface clocks via the di_pre_sel and di_sel muxes by default.

---
  arch/arm/mach-imx/clk-imx6q.c | 9 +++++++++
  1 file changed, 9 insertions(+)
arch/arm/mach-imx/clk-imx6q.c +2 -0
index a3a69ab..ba17299 100644
@@ -445,6 +445,15 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
  		clk_set_parent(clk[ldb_di1_sel], clk[pll5_video_div]);
  	}
 
+	clk_set_parent(clk[ipu1_di0_pre_sel], clk[pll5_video_div]);
+	clk_set_parent(clk[ipu1_di1_pre_sel], clk[pll5_video_div]);

arch/arm/mach-imx/clk-imx6q.c static void __init imx6q_clocks_init(struct device_node *ccm_node) · line 459

Quoted 10 lines
arch/arm/mach-imx/clk-imx6q.c +7 -0
+	clk_set_parent(clk[ipu2_di0_pre_sel], clk[pll5_video_div]);
+	clk_set_parent(clk[ipu2_di1_pre_sel], clk[pll5_video_div]);
+	clk_set_parent(clk[ipu1_di0_sel], clk[ipu1_di0_pre]);
+	clk_set_parent(clk[ipu1_di1_sel], clk[ipu1_di1_pre]);
+	clk_set_parent(clk[ipu2_di0_sel], clk[ipu2_di0_pre]);
+	clk_set_parent(clk[ipu2_di1_sel], clk[ipu2_di1_pre]);
+
  	/*
  	 * The gpmi needs 100MHz frequency in the EDO/Sync mode,
  	 * We can not get the 100MHz from the pll2_pfd0_352m.

I'm no expert on this, so just a question from an internal review:

Quoted 4 lines

With this, having both ldb_di0_sel and ipu1_di0_sel driven by pll5_video, what will happen if both lvds and hdmi are trying to set the rate of pll5_video_div?

Last one that comes around wins. We could change this to use clock notifiers, but it doesn't make much sense right now, as this would just change the situation to first one wins.

What we really need is some kind of clock negotiation, but there isn't anything in the clock framework yet to make this happen. We have some ideas about this, but it will take a little while.

In the meanwhile this patch improves the situation for people using the driver with one LVDS or HDMI display.

Regards,
Lucas

Signature · 2 lines
Pengutronix e.K.             | Lucas Stach                 |
Industrial Linux Solutions   | http://www.pengutronix.de/  |
#6 lore raw

PATCH 1/2 ARM: imx6q: clk: Parent DI clocks to video PLL via di_pre_sel

In reply to Dirk Behme
Quoted 35 lines · Dirk Behme
Quoted 21 lines · Philipp Zabel

From: Sascha Hauer <[email protected]>

Route the video PLL to the display interface clocks via the di_pre_sel and di_sel muxes by default.

---
 arch/arm/mach-imx/clk-imx6q.c | 9 +++++++++
 1 file changed, 9 insertions(+)
arch/arm/mach-imx/clk-imx6q.c +2 -0
index a3a69ab..ba17299 100644
@@ -445,6 +445,15 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 		clk_set_parent(clk[ldb_di1_sel], clk[pll5_video_div]);
 	}
 
+	clk_set_parent(clk[ipu1_di0_pre_sel], clk[pll5_video_div]);
+	clk_set_parent(clk[ipu1_di1_pre_sel], clk[pll5_video_div]);

arch/arm/mach-imx/clk-imx6q.c static void __init imx6q_clocks_init(struct device_node *ccm_node) · line 459

Quoted 10 lines
arch/arm/mach-imx/clk-imx6q.c +7 -0
+	clk_set_parent(clk[ipu2_di0_pre_sel], clk[pll5_video_div]);
+	clk_set_parent(clk[ipu2_di1_pre_sel], clk[pll5_video_div]);
+	clk_set_parent(clk[ipu1_di0_sel], clk[ipu1_di0_pre]);
+	clk_set_parent(clk[ipu1_di1_sel], clk[ipu1_di1_pre]);
+	clk_set_parent(clk[ipu2_di0_sel], clk[ipu2_di0_pre]);
+	clk_set_parent(clk[ipu2_di1_sel], clk[ipu2_di1_pre]);
+
 	/*
 	 * The gpmi needs 100MHz frequency in the EDO/Sync mode,
 	 * We can not get the 100MHz from the pll2_pfd0_352m.

I'm no expert on this, so just a question from an internal review:

Quoted 3 lines

With this, having both ldb_di0_sel and ipu1_di0_sel driven by pll5_video, what will happen if both lvds and hdmi are trying to set the rate of pll5_video_div?

It's indeed a good question.

Very likely, one or the other will be broken, depending which one calls clk_set_rate() first. The one calling clk_set_rate() later will work fine.

It's a result of that there is no negotiation between rate change requests from different clients on the same clock. Such negotiation can be done with clk rate change notifier. It will make these client driver quite complex on clk set rate operation though. Also, if none of the possible rate of the source clock can meet the different requests from these clients at the same time, we're stuck anyway.

That said, for now we have limitation to support both lvds and hdmi.

Shawn