[RFC] drm/tegra: Add a flag to mark that there is only one display pll

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



There is a workaround in which the tegra rgb driver initializes
the tegra dc pclk to 0 so that it will skip setting the parent clk rate.

The relevant commits:
3cebae6737b100323baca21de6bce6647249e778
76d59ed049197bdaaa24c0e061a105af6ce74457

A more recent commit sets the rate of the dc clk itself:
39e08affecf0998be1b01f4752016e33fa98eb9a

This doesn't make sense because it always sets the dc clk to 0.
Is this intended behavior or does it just happen to be working for
the current tegra 2 boards in the mainline kernel?


For context I am running the kernel on a tegra 2 based
Galaxy Tab 10.1. The display panel driver is out of tree.
This panel has very low clock rate tolerances so it must be
driven at a rate very close to the required specification (68.75Mhz).
pll_p is not adequate to drive this panel so pll_d must be used.

Another issue is the current workaround is always forcing the disp1
clk to zero. The Galaxy Tab 10.1 locks up completely when calling
clk_set_rate with a clk rate of 0 whether the parent is pll_p or
pll_d.


This patch adds a flag single_display_pll to mark that the device has
only one display pll. This replaces the the pclk = 0 workaround.

There is a comment in rgb.c about using the shift clock divider for
tegra 2 but the divider is not set due to the has_nvdisplay flag.
This patch also sets the shift clock divider based on the
single_display_pll flag.

A change I'm uncertain about. In tegra_dc_commit_state()
the dc clock is now being set to the display panel rate rather than zero.

I don't have any other tegra devices to test with. So I don't know
if this breaks other devices. Previously the code was trying to set the
clock rate to zero anyways.

Signed-off-by: ryang <decatf@xxxxxxxxx>
---
 drivers/gpu/drm/tegra/dc.c  | 9 +++++++--
 drivers/gpu/drm/tegra/dc.h  | 1 +
 drivers/gpu/drm/tegra/rgb.c | 1 -
 3 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 965088afcfad..03f1ad630254 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -1664,7 +1664,7 @@ static void tegra_dc_commit_state(struct tegra_dc *dc,
 	 * which is shared with other peripherals. Changing the clock rate
 	 * should therefore be avoided.
 	 */
-	if (state->pclk > 0) {
+	if (!dc->soc->single_display_pll) {
 		err = clk_set_rate(state->clk, state->pclk);
 		if (err < 0)
 			dev_err(dc->dev,
@@ -1676,7 +1676,7 @@ static void tegra_dc_commit_state(struct tegra_dc *dc,
 		      state->div);
 	DRM_DEBUG_KMS("pclk: %lu\n", state->pclk);
 
-	if (!dc->soc->has_nvdisplay) {
+	if (!dc->soc->has_nvdisplay || dc->soc->single_display_pll) {
 		value = SHIFT_CLK_DIVIDER(state->div) | PIXEL_CLK_DIVIDER_PCD1;
 		tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);
 	}
@@ -2108,6 +2108,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
 	.modifiers = tegra20_modifiers,
 	.has_win_a_without_filters = true,
 	.has_win_c_without_vert_filter = true,
+	.single_display_pll = true,
 };
 
 static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
@@ -2127,6 +2128,7 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
 	.modifiers = tegra20_modifiers,
 	.has_win_a_without_filters = false,
 	.has_win_c_without_vert_filter = false,
+	.single_display_pll = false,
 };
 
 static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
@@ -2146,6 +2148,7 @@ static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
 	.modifiers = tegra20_modifiers,
 	.has_win_a_without_filters = false,
 	.has_win_c_without_vert_filter = false,
+	.single_display_pll = false,
 };
 
 static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
@@ -2165,6 +2168,7 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
 	.modifiers = tegra124_modifiers,
 	.has_win_a_without_filters = false,
 	.has_win_c_without_vert_filter = false,
+	.single_display_pll = false,
 };
 
 static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
@@ -2184,6 +2188,7 @@ static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
 	.modifiers = tegra124_modifiers,
 	.has_win_a_without_filters = false,
 	.has_win_c_without_vert_filter = false,
+	.single_display_pll = false,
 };
 
 static const struct tegra_windowgroup_soc tegra186_dc_wgrps[] = {
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index e96f582ca692..abe75d4ad8bd 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -69,6 +69,7 @@ struct tegra_dc_soc_info {
 	const u64 *modifiers;
 	bool has_win_a_without_filters;
 	bool has_win_c_without_vert_filter;
+	bool single_display_pll;
 };
 
 struct tegra_dc {
diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c
index 28a78d3120bc..53a872a03dea 100644
--- a/drivers/gpu/drm/tegra/rgb.c
+++ b/drivers/gpu/drm/tegra/rgb.c
@@ -196,7 +196,6 @@ tegra_rgb_encoder_atomic_check(struct drm_encoder *encoder,
 	 * matched sufficiently close that the panel will still work).
 	 */
 	div = ((clk_get_rate(rgb->clk) * 2) / pclk) - 2;
-	pclk = 0;
 
 	err = tegra_dc_state_setup_clock(dc, crtc_state, rgb->clk_parent,
 					 pclk, div);
-- 
2.17.1




[Index of Archives]     [ARM Kernel]     [Linux ARM]     [Linux ARM MSM]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux