DISP1 clock may use PLLP, PLLC and PLLD as parents.
Instead of hardcoding, lets pass clock and its
parent from device tree. Default parent is PLLP.

Tested-by: Robert Eckelmann <longnose...@gmail.com> # ASUS TF101 T20
Tested-by: Nicolas Chauvet <kwiz...@gmail.com> # Paz00
Tested-by: Andreas Westman Dorcsak <hed...@yahoo.com> # ASUS TF T30
Tested-by: Svyatoslav Ryhel <clamo...@gmail.com> # HTC One X T30
Signed-off-by: Svyatoslav Ryhel <clamo...@gmail.com>
---
 drivers/video/tegra20/tegra-dc.c | 31 +++++++++++++++++++++++--------
 1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c
index 5e3f6bf029..ff67cc8989 100644
--- a/drivers/video/tegra20/tegra-dc.c
+++ b/drivers/video/tegra20/tegra-dc.c
@@ -36,6 +36,7 @@ struct tegra_lcd_priv {
        struct disp_ctlr *disp;         /* Display controller to use */
        fdt_addr_t frame_buffer;        /* Address of frame buffer */
        unsigned pixel_clock;           /* Pixel clock in Hz */
+       int dc_clk[2];                  /* Contains clk and its parent */
 };
 
 enum {
@@ -134,7 +135,7 @@ static int update_display_mode(struct dc_disp_reg *disp,
         * the display clock (typically 600MHz) to the pixel clock. We round
         * up or down as requried.
         */
-       rate = clock_get_periph_rate(PERIPH_ID_DISP1, CLOCK_ID_CGENERAL);
+       rate = clock_get_periph_rate(priv->dc_clk[0], priv->dc_clk[1]);
        div = ((rate * 2 + priv->pixel_clock / 2) / priv->pixel_clock) - 2;
        debug("Display clock %lu, divider %lu\n", rate, div);
 
@@ -269,20 +270,27 @@ static int tegra_display_probe(const void *blob, struct 
tegra_lcd_priv *priv,
 {
        struct disp_ctl_win window;
        struct dc_ctlr *dc;
+       unsigned long rate = clock_get_rate(priv->dc_clk[1]);
 
        priv->frame_buffer = (u32)default_lcd_base;
 
        dc = (struct dc_ctlr *)priv->disp;
 
        /*
-        * A header file for clock constants was NAKed upstream.
-        * TODO: Put this into the FDT and fdt_lcd struct when we have clock
-        * support there
+        * We halve the rate if DISP1 paret is PLLD, since actual parent
+        * is plld_out0 which is PLLD divided by 2.
         */
-       clock_start_periph_pll(PERIPH_ID_HOST1X, CLOCK_ID_PERIPH,
-                              144 * 1000000);
-       clock_start_periph_pll(PERIPH_ID_DISP1, CLOCK_ID_CGENERAL,
-                              600 * 1000000);
+       if (priv->dc_clk[1] == CLOCK_ID_DISPLAY)
+               rate /= 2;
+
+       /*
+        * HOST1X is init by default at 150MHz with PLLC as parent
+        */
+       clock_start_periph_pll(PERIPH_ID_HOST1X, CLOCK_ID_CGENERAL,
+                              150 * 1000000);
+       clock_start_periph_pll(priv->dc_clk[0], priv->dc_clk[1],
+                              rate);
+
        basic_init(&dc->cmd);
        basic_init_timer(&dc->disp);
        rgb_enable(&dc->com);
@@ -358,6 +366,13 @@ static int tegra_lcd_of_to_plat(struct udevice *dev)
                return -EINVAL;
        }
 
+       ret = clock_decode_pair(dev, priv->dc_clk);
+       if (ret < 0) {
+               debug("%s: Cannot decode clocks for '%s' (ret = %d)\n",
+                     __func__, dev->name, ret);
+               return -EINVAL;
+       }
+
        rgb = fdt_subnode_offset(blob, node, "rgb");
        if (rgb < 0) {
                debug("%s: Cannot find rgb subnode for '%s' (ret=%d)\n",
-- 
2.37.2

Reply via email to