video: tegra20: dc: configure behavior if PLLD/D2 is used
If DISP1 is a PLLD/D2 child, it cannot go over 370MHz. The cause
of this is not quite clear. This can be overcomed by further
halving the PLLD/D2 if the target parent rate is over 800MHz.
This way DISP1 and DSI clocks will have the same frequency. The
shift divider in this case has to be calculated from the
original PLLD/D2 frequency and is passed from the DSI driver.
Tested-by: Andreas Westman Dorcsak <hedmoo@yahoo.com> # ASUS Grouper E1565
Tested-by: Ion Agorria <ion@agorria.com> # HTC One X
Tested-by: Svyatoslav Ryhel <clamor95@gmail.com> # Nvidia Tegratab T114
Tested-by: Jonas Schwöbel <jonasschwoebel@yahoo.de> # Microsoft Surface 2
Signed-off-by: Jonas Schwöbel <jonasschwoebel@yahoo.de>
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Acked-by: Thierry Reding <treding@nvidia.com>
diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c
index 72b91ed..de225ed 100644
--- a/drivers/video/tegra20/tegra-dsi.c
+++ b/drivers/video/tegra20/tegra-dsi.c
@@ -743,6 +743,7 @@
static void tegra_dsi_init_clocks(struct udevice *dev)
{
struct tegra_dsi_priv *priv = dev_get_priv(dev);
+ struct tegra_dc_plat *dc_plat = dev_get_plat(dev);
struct mipi_dsi_device *device = &priv->device;
unsigned int mul, div;
unsigned long bclk, plld;
@@ -754,6 +755,19 @@
plld = DIV_ROUND_UP(bclk * 8, USEC_PER_SEC);
+ dc_plat->scdiv = ((plld * USEC_PER_SEC +
+ priv->timing.pixelclock.typ / 2) /
+ priv->timing.pixelclock.typ) - 2;
+
+ /*
+ * BUG: If DISP1 is a PLLD/D2 child, it cannot go over 370MHz. The
+ * cause of this is not quite clear. This can be overcomed by
+ * halving the PLLD/D2 if the target rate is > 800MHz. This way
+ * DISP1 and DSI clocks will be equal.
+ */
+ if (plld > 800)
+ plld /= 2;
+
switch (clock_get_osc_freq()) {
case CLOCK_OSC_FREQ_12_0: /* OSC is 12Mhz */
case CLOCK_OSC_FREQ_48_0: /* OSC is 48Mhz */