diff options
-rw-r--r-- | arch/arm/mach-tegra/include/mach/dc.h | 1 | ||||
-rw-r--r-- | drivers/video/tegra/dc/dc.c | 26 |
2 files changed, 27 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/include/mach/dc.h b/arch/arm/mach-tegra/include/mach/dc.h index caca9d84c1be..4137a8f11017 100644 --- a/arch/arm/mach-tegra/include/mach/dc.h +++ b/arch/arm/mach-tegra/include/mach/dc.h @@ -324,6 +324,7 @@ struct tegra_dc_out { int dcc_bus; int hotplug_gpio; const char *parent_clk; + const char *parent_clk_backup; unsigned max_pixclock; unsigned order; diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index 951e8caaff2e..45962baa9fce 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c @@ -1362,6 +1362,21 @@ static unsigned long tegra_dc_pclk_round_rate(struct tegra_dc *dc, int pclk) return rate * 2 / div; } +static unsigned long tegra_dc_pclk_predict_rate(struct clk *parent, int pclk) +{ + unsigned long rate; + unsigned long div; + + rate = clk_get_rate(parent); + + div = DIV_ROUND_CLOSEST(rate * 2, pclk); + + if (div < 2) + return 0; + + return rate * 2 / div; +} + void tegra_dc_setup_clk(struct tegra_dc *dc, struct clk *clk) { int pclk; @@ -1371,6 +1386,17 @@ void tegra_dc_setup_clk(struct tegra_dc *dc, struct clk *clk) struct clk *parent_clk = clk_get_sys(NULL, dc->out->parent_clk ? : "pll_p"); + if (dc->out->parent_clk_backup && + (parent_clk == clk_get_sys(NULL, "pll_p"))) { + rate = tegra_dc_pclk_predict_rate( + parent_clk, dc->mode.pclk); + /* use pll_d as last resort */ + if (rate < (dc->mode.pclk / 100 * 99) || + rate > (dc->mode.pclk / 100 * 109)) + parent_clk = clk_get_sys( + NULL, dc->out->parent_clk_backup); + } + if (clk_get_parent(clk) != parent_clk) clk_set_parent(clk, parent_clk); |