video: tegra-dc: get clocks from device tree

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 <longnoserob@gmail.com> # ASUS TF101 T20
Tested-by: Nicolas Chauvet <kwizart@gmail.com> # Paz00
Tested-by: Andreas Westman Dorcsak <hedmoo@yahoo.com> # ASUS TF T30
Tested-by: Svyatoslav Ryhel <clamor95@gmail.com> # HTC One X T30
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c
index 5e3f6bf..ff67cc8 100644
--- a/drivers/video/tegra20/tegra-dc.c
+++ b/drivers/video/tegra20/tegra-dc.c
@@ -36,6 +36,7 @@
 	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 @@
 	 * 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 @@
 {
 	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 @@
 		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",