diff --git a/drivers/video/sunxi/sunxi_dw_hdmi.c b/drivers/video/sunxi/sunxi_dw_hdmi.c
index 9dbea649a0ff709da88a28c7859f9c9b60511f11..6fe1aa7ee469590e67b7be513d7755f1ceb67456 100644
--- a/drivers/video/sunxi/sunxi_dw_hdmi.c
+++ b/drivers/video/sunxi/sunxi_dw_hdmi.c
@@ -132,7 +132,7 @@ static int sunxi_dw_hdmi_wait_for_hpd(void)
 	return -1;
 }
 
-static void sunxi_dw_hdmi_phy_set(uint clock)
+static void sunxi_dw_hdmi_phy_set(uint clock, int phy_div)
 {
 	struct sunxi_hdmi_phy * const phy =
 		(struct sunxi_hdmi_phy *)(SUNXI_HDMI_BASE + HDMI_PHY_OFFS);
@@ -146,7 +146,7 @@ static void sunxi_dw_hdmi_phy_set(uint clock)
 	switch (div) {
 	case 1:
 		writel(0x30dc5fc0, &phy->pll);
-		writel(0x800863C0, &phy->clk);
+		writel(0x800863C0 | (phy_div - 1), &phy->clk);
 		mdelay(10);
 		writel(0x00000001, &phy->unk3);
 		setbits_le32(&phy->pll, BIT(25));
@@ -164,7 +164,7 @@ static void sunxi_dw_hdmi_phy_set(uint clock)
 		break;
 	case 2:
 		writel(0x39dc5040, &phy->pll);
-		writel(0x80084381, &phy->clk);
+		writel(0x80084380 | (phy_div - 1), &phy->clk);
 		mdelay(10);
 		writel(0x00000001, &phy->unk3);
 		setbits_le32(&phy->pll, BIT(25));
@@ -178,7 +178,7 @@ static void sunxi_dw_hdmi_phy_set(uint clock)
 		break;
 	case 4:
 		writel(0x39dc5040, &phy->pll);
-		writel(0x80084343, &phy->clk);
+		writel(0x80084340 | (phy_div - 1), &phy->clk);
 		mdelay(10);
 		writel(0x00000001, &phy->unk3);
 		setbits_le32(&phy->pll, BIT(25));
@@ -192,7 +192,7 @@ static void sunxi_dw_hdmi_phy_set(uint clock)
 		break;
 	case 11:
 		writel(0x39dc5040, &phy->pll);
-		writel(0x8008430a, &phy->clk);
+		writel(0x80084300 | (phy_div - 1), &phy->clk);
 		mdelay(10);
 		writel(0x00000001, &phy->unk3);
 		setbits_le32(&phy->pll, BIT(25));
@@ -207,36 +207,46 @@ static void sunxi_dw_hdmi_phy_set(uint clock)
 	}
 }
 
-static void sunxi_dw_hdmi_pll_set(uint clk_khz)
+static void sunxi_dw_hdmi_pll_set(uint clk_khz, int *phy_div)
 {
-	int value, n, m, div = 0, diff;
-	int best_n = 0, best_m = 0, best_diff = 0x0FFFFFFF;
-
-	div = sunxi_dw_hdmi_get_divider(clk_khz * 1000);
+	int value, n, m, div, diff;
+	int best_n = 0, best_m = 0, best_div = 0, best_diff = 0x0FFFFFFF;
 
 	/*
 	 * Find the lowest divider resulting in a matching clock. If there
 	 * is no match, pick the closest lower clock, as monitors tend to
 	 * not sync to higher frequencies.
 	 */
-	for (m = 1; m <= 16; m++) {
-		n = (m * div * clk_khz) / 24000;
-
-		if ((n >= 1) && (n <= 128)) {
-			value = (24000 * n) / m / div;
-			diff = clk_khz - value;
-			if (diff < best_diff) {
-				best_diff = diff;
-				best_m = m;
-				best_n = n;
+	for (div = 1; div <= 16; div++) {
+		int target = clk_khz * div;
+
+		if (target < 192000)
+			continue;
+		if (target > 912000)
+			continue;
+
+		for (m = 1; m <= 16; m++) {
+			n = (m * target) / 24000;
+
+			if (n >= 1 && n <= 128) {
+				value = (24000 * n) / m / div;
+				diff = clk_khz - value;
+				if (diff < best_diff) {
+					best_diff = diff;
+					best_m = m;
+					best_n = n;
+					best_div = div;
+				}
 			}
 		}
 	}
 
+	*phy_div = best_div;
+
 	clock_set_pll3_factors(best_m, best_n);
 	debug("dotclock: %dkHz = %dkHz: (24MHz * %d) / %d / %d\n",
-	      clk_khz, (clock_get_pll3() / 1000) / div,
-	      best_n, best_m, div);
+	      clk_khz, (clock_get_pll3() / 1000) / best_div,
+	      best_n, best_m, best_div);
 }
 
 static void sunxi_dw_hdmi_lcdc_init(int mux, const struct display_timing *edid,
@@ -244,7 +254,7 @@ static void sunxi_dw_hdmi_lcdc_init(int mux, const struct display_timing *edid,
 {
 	struct sunxi_ccm_reg * const ccm =
 		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
-	int div = sunxi_dw_hdmi_get_divider(edid->pixelclock.typ);
+	int div = clock_get_pll3() / edid->pixelclock.typ;
 	struct sunxi_lcdc_reg *lcdc;
 
 	if (mux == 0) {
@@ -276,8 +286,10 @@ static void sunxi_dw_hdmi_lcdc_init(int mux, const struct display_timing *edid,
 
 static int sunxi_dw_hdmi_phy_cfg(struct dw_hdmi *hdmi, uint mpixelclock)
 {
-	sunxi_dw_hdmi_pll_set(mpixelclock/1000);
-	sunxi_dw_hdmi_phy_set(mpixelclock);
+	int phy_div;
+
+	sunxi_dw_hdmi_pll_set(mpixelclock / 1000, &phy_div);
+	sunxi_dw_hdmi_phy_set(mpixelclock, phy_div);
 
 	return 0;
 }