CTS_VDAC_EN, CTS_VDAC_EN);
 }
 
-
+enum {
 /* PLL O1 O2 O3 VP DV     EN TX */
 /* 4320 /4 /4 /1 /5 /1  => /2 /2 */
-#define MESON_VCLK_HDMI_ENCI_54000     1
+       MESON_VCLK_HDMI_ENCI_54000 = 1,
 /* 4320 /4 /4 /1 /5 /1  => /1 /2 */
-#define MESON_VCLK_HDMI_DDR_54000      2
+       MESON_VCLK_HDMI_DDR_54000,
 /* 2970 /4 /1 /1 /5 /1  => /1 /2 */
-#define MESON_VCLK_HDMI_DDR_148500     3
-/* 4028 /4 /4 /1 /5 /2  => /1 /1 */
-#define MESON_VCLK_HDMI_25175          4
-/* 3200 /4 /2 /1 /5 /2  => /1 /1 */
-#define MESON_VCLK_HDMI_40000          5
-/* 5200 /4 /2 /1 /5 /2  => /1 /1 */
-#define MESON_VCLK_HDMI_65000          6
+       MESON_VCLK_HDMI_DDR_148500,
 /* 2970 /2 /2 /2 /5 /1  => /1 /1 */
-#define MESON_VCLK_HDMI_74250          7
-/* 4320 /4 /1 /1 /5 /2  => /1 /1 */
-#define MESON_VCLK_HDMI_108000         8
+       MESON_VCLK_HDMI_74250,
 /* 2970 /1 /2 /2 /5 /1  => /1 /1 */
-#define MESON_VCLK_HDMI_148500         9
-/* 3240 /2 /1 /1 /5 /2  => /1 /1 */
-#define MESON_VCLK_HDMI_162000         10
+       MESON_VCLK_HDMI_148500,
 /* 2970 /1 /1 /1 /5 /2  => /1 /1 */
-#define MESON_VCLK_HDMI_297000         11
+       MESON_VCLK_HDMI_297000,
 /* 5940 /1 /1 /2 /5 /1  => /1 /1 */
-#define MESON_VCLK_HDMI_594000         12
+       MESON_VCLK_HDMI_594000
+};
 
 struct meson_vclk_params {
        unsigned int pll_base_freq;
                .vid_pll_div = VID_PLL_DIV_5,
                .vclk_div = 1,
        },
-       [MESON_VCLK_HDMI_25175] = {
-               .pll_base_freq = 4028000,
-               .pll_od1 = 4,
-               .pll_od2 = 4,
-               .pll_od3 = 1,
-               .vid_pll_div = VID_PLL_DIV_5,
-               .vclk_div = 2,
-       },
-       [MESON_VCLK_HDMI_40000] = {
-               .pll_base_freq = 3200000,
-               .pll_od1 = 4,
-               .pll_od2 = 2,
-               .pll_od3 = 1,
-               .vid_pll_div = VID_PLL_DIV_5,
-               .vclk_div = 2,
-       },
-       [MESON_VCLK_HDMI_65000] = {
-               .pll_base_freq = 5200000,
-               .pll_od1 = 4,
-               .pll_od2 = 2,
-               .pll_od3 = 1,
-               .vid_pll_div = VID_PLL_DIV_5,
-               .vclk_div = 2,
-       },
-       [MESON_VCLK_HDMI_108000] = {
-               .pll_base_freq = 4320000,
-               .pll_od1 = 4,
-               .pll_od2 = 1,
-               .pll_od3 = 1,
-               .vid_pll_div = VID_PLL_DIV_5,
-               .vclk_div = 2,
-       },
-       [MESON_VCLK_HDMI_162000] = {
-               .pll_base_freq = 3240000,
-               .pll_od1 = 2,
-               .pll_od2 = 1,
-               .pll_od3 = 1,
-               .vid_pll_div = VID_PLL_DIV_5,
-               .vclk_div = 2,
-       },
 };
 
 static inline unsigned int pll_od_to_reg(unsigned int od)
        return 0;
 }
 
-void meson_hdmi_pll_set(struct meson_drm *priv,
-                       unsigned int base,
-                       unsigned int od1,
-                       unsigned int od2,
-                       unsigned int od3)
+void meson_hdmi_pll_set_params(struct meson_drm *priv, unsigned int m,
+                              unsigned int frac, unsigned int od1,
+                              unsigned int od2, unsigned int od3)
 {
        unsigned int val;
 
        if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
-               switch (base) {
-               case 2970000:
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800023d);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
-
-                       /* Enable and unreset */
-                       regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
-                                               0x7 << 28, 0x4 << 28);
-
-                       /* Poll for lock bit */
-                       regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
-                                       val, (val & HDMI_PLL_LOCK), 10, 0);
-
-                       /* div_frac */
-                       regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
-                                               0xFFFF,  0x4e00);
-                       break;
-
-               case 3200000:
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x58000242);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
-
-                       /* unreset */
-                       regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
-                                               BIT(28), 0);
-
-                       /* Poll for lock bit */
-                       regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
-                                       val, (val & HDMI_PLL_LOCK), 10, 0);
-
-                       /* div_frac */
-                       regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
-                                               0xFFFF,  0x4aab);
-                       break;
-
-               case 3240000:
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x58000243);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
-
-                       /* unreset */
-                       regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
-                                               BIT(28), 0);
-
-                       /* Poll for lock bit */
-                       regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
-                                       val, (val & HDMI_PLL_LOCK), 10, 0);
-
-                       /* div_frac */
-                       regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
-                                               0xFFFF,  0x4800);
-                       break;
-
-               case 3865000:
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x58000250);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
-
-                       /* unreset */
-                       regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
-                                               BIT(28), 0);
-
-                       /* Poll for lock bit */
-                       regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
-                                       val, (val & HDMI_PLL_LOCK), 10, 0);
-
-                       /* div_frac */
-                       regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
-                                               0xFFFF,  0x4855);
-                       break;
-
-               case 4028000:
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x58000253);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
-
-                       /* unreset */
-                       regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
-                                               BIT(28), 0);
-
-                       /* Poll for lock bit */
-                       regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
-                                       val, (val & HDMI_PLL_LOCK), 10, 0);
-
-                       /* div_frac */
-                       regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
-                                               0xFFFF,  0x4eab);
-                       break;
-
-               case 4320000:
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800025a);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
-
-                       /* unreset */
-                       regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
-                                               BIT(28), 0);
-
-                       /* Poll for lock bit */
-                       regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
-                                       val, (val & HDMI_PLL_LOCK), 10, 0);
-                       break;
+               regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x58000200 | m);
+               if (frac)
+                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2,
+                                    0x00004000 | frac);
+               else
+                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2,
+                                    0x00000000);
+               regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
+               regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
+               regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
+               regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
 
-               case 5940000:
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800027b);
-                       regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
-                                               0xFFFF,  0x4c00);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x135c5091);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
-
-                       /* unreset */
-                       regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
-                                               BIT(28), 0);
-
-                       /* Poll for lock bit */
-                       regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
-                                       val, (val & HDMI_PLL_LOCK), 10, 0);
-                       break;
+               /* Enable and unreset */
+               regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+                                  0x7 << 28, 0x4 << 28);
 
-               case 5200000:
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800026c);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x135c5091);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
-
-                       /* unreset */
-                       regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
-                                               BIT(28), 0);
-
-                       /* Poll for lock bit */
-                       regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
-                                       val, (val & HDMI_PLL_LOCK), 10, 0);
-                       break;
-               };
+               /* Poll for lock bit */
+               regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
+                                        val, (val & HDMI_PLL_LOCK), 10, 0);
        } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
                   meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
-               switch (base) {
-               case 2970000:
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4000027b);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb300);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
-                       break;
-
-               case 3200000:
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x40000285);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb155);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
-                       break;
-
-               case 3240000:
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x40000287);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb000);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
-                       break;
-
-               case 3865000:
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002a1);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb02b);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
-                       break;
-
-               case 4028000:
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002a7);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb355);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
-                       break;
-
-               case 4320000:
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002b4);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb000);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
-                       break;
-
-               case 5940000:
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002f7);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb200);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
-                       break;
-
-               case 5200000:
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002d8);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb2ab);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
-                       regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
-                       break;
-
-               };
+               regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x40000200 | m);
+               regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb000 | frac);
+               regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
+               regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
+               regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
+               regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
 
                /* Reset PLL */
                regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
-                                       HDMI_PLL_RESET, HDMI_PLL_RESET);
+                               HDMI_PLL_RESET, HDMI_PLL_RESET);
                regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
-                                       HDMI_PLL_RESET, 0);
+                               HDMI_PLL_RESET, 0);
 
                /* Poll for lock bit */
                regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
                                (val & HDMI_PLL_LOCK), 10, 0);
-       };
+       }
 
        if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
                regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
-                                  3 << 16, pll_od_to_reg(od1) << 16);
+                               3 << 16, pll_od_to_reg(od1) << 16);
        else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
-                meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
+                       meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
                regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
-                                  3 << 21, pll_od_to_reg(od1) << 21);
+                               3 << 21, pll_od_to_reg(od1) << 21);
 
        if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
                regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
-                                  3 << 22, pll_od_to_reg(od2) << 22);
+                               3 << 22, pll_od_to_reg(od2) << 22);
        else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
-                meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
+                       meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
                regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
-                                  3 << 23, pll_od_to_reg(od2) << 23);
+                               3 << 23, pll_od_to_reg(od2) << 23);
 
        if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
                regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
-                                  3 << 18, pll_od_to_reg(od3) << 18);
+                               3 << 18, pll_od_to_reg(od3) << 18);
        else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
-                meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
+                       meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
                regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
-                                  3 << 19, pll_od_to_reg(od3) << 19);
+                               3 << 19, pll_od_to_reg(od3) << 19);
+
 }
 
-void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
-                     unsigned int vclk_freq, unsigned int venc_freq,
-                     unsigned int dac_freq, bool hdmi_use_enci)
+#define XTAL_FREQ 24000
+
+static unsigned int meson_hdmi_pll_get_m(struct meson_drm *priv,
+                                        unsigned int pll_freq)
 {
-       unsigned int freq;
-       unsigned int hdmi_tx_div;
-       unsigned int venc_div;
+       /* The GXBB PLL has a /2 pre-multiplier */
+       if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
+               pll_freq /= 2;
 
-       if (target == MESON_VCLK_TARGET_CVBS) {
-               meson_venci_cvbs_clock_config(priv);
-               return;
+       return pll_freq / XTAL_FREQ;
+}
+
+#define HDMI_FRAC_MAX_GXBB     4096
+#define HDMI_FRAC_MAX_GXL      1024
+
+static unsigned int meson_hdmi_pll_get_frac(struct meson_drm *priv,
+                                           unsigned int m,
+                                           unsigned int pll_freq)
+{
+       unsigned int parent_freq = XTAL_FREQ;
+       unsigned int frac_max = HDMI_FRAC_MAX_GXL;
+       unsigned int frac_m;
+       unsigned int frac;
+
+       /* The GXBB PLL has a /2 pre-multiplier and a larger FRAC width */
+       if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
+               frac_max = HDMI_FRAC_MAX_GXBB;
+               parent_freq *= 2;
        }
 
-       hdmi_tx_div = vclk_freq / dac_freq;
+       /* We can have a perfect match !*/
+       if (pll_freq / m == parent_freq &&
+           pll_freq % m == 0)
+               return 0;
 
-       if (hdmi_tx_div == 0) {
-               pr_err("Fatal Error, invalid HDMI-TX freq %d\n",
-                               dac_freq);
-               return;
+       frac = div_u64((u64)pll_freq * (u64)frac_max, parent_freq);
+       frac_m = m * frac_max;
+       if (frac_m > frac)
+               return frac_max;
+       frac -= frac_m;
+
+       return min((u16)frac, (u16)(frac_max - 1));
+}
+
+static bool meson_hdmi_pll_validate_params(struct meson_drm *priv,
+                                          unsigned int m,
+                                          unsigned int frac)
+{
+       if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
+               /* Empiric supported min/max dividers */
+               if (m < 53 || m > 123)
+                       return false;
+               if (frac >= HDMI_FRAC_MAX_GXBB)
+                       return false;
+       } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
+                  meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
+               /* Empiric supported min/max dividers */
+               if (m < 106 || m > 247)
+                       return false;
+               if (frac >= HDMI_FRAC_MAX_GXL)
+                       return false;
        }
 
-       venc_div = vclk_freq / venc_freq;
+       return true;
+}
 
-       if (venc_div == 0) {
-               pr_err("Fatal Error, invalid HDMI venc freq %d\n",
-                               venc_freq);
-               return;
+static bool meson_hdmi_pll_find_params(struct meson_drm *priv,
+                                      unsigned int freq,
+                                      unsigned int *m,
+                                      unsigned int *frac,
+                                      unsigned int *od)
+{
+       /* Cycle from /16 to /2 */
+       for (*od = 16 ; *od > 1 ; *od >>= 1) {
+               *m = meson_hdmi_pll_get_m(priv, freq * *od);
+               if (!*m)
+                       continue;
+               *frac = meson_hdmi_pll_get_frac(priv, *m, freq * *od);
+
+               DRM_DEBUG_DRIVER("PLL params for %dkHz: m=%x frac=%x od=%d\n",
+                                freq, *m, *frac, *od);
+
+               if (meson_hdmi_pll_validate_params(priv, *m, *frac))
+                       return true;
        }
 
-       switch (vclk_freq) {
-       case 54000:
-               if (hdmi_use_enci)
-                       freq = MESON_VCLK_HDMI_ENCI_54000;
-               else
-                       freq = MESON_VCLK_HDMI_DDR_54000;
-               break;
-       case 25175:
-               freq = MESON_VCLK_HDMI_25175;
-               break;
-       case 40000:
-               freq = MESON_VCLK_HDMI_40000;
-               break;
-       case 65000:
-               freq = MESON_VCLK_HDMI_65000;
-               break;
-       case 74250:
-               freq = MESON_VCLK_HDMI_74250;
-               break;
-       case 108000:
-               freq = MESON_VCLK_HDMI_108000;
-               break;
-       case 148500:
-               if (dac_freq != 148500)
-                       freq = MESON_VCLK_HDMI_DDR_148500;
-               else
-                       freq = MESON_VCLK_HDMI_148500;
-               break;
-       case 162000:
-               freq = MESON_VCLK_HDMI_162000;
-               break;
-       case 297000:
-               freq = MESON_VCLK_HDMI_297000;
-               break;
-       case 594000:
-               freq = MESON_VCLK_HDMI_594000;
-               break;
-       default:
-               pr_err("Fatal Error, invalid HDMI vclk freq %d\n",
-                       vclk_freq);
+       return false;
+}
+
+/* pll_freq is the frequency after the OD dividers */
+enum drm_mode_status
+meson_vclk_dmt_supported_freq(struct meson_drm *priv, unsigned int freq)
+{
+       unsigned int od, m, frac;
+
+       /* In DMT mode, path after PLL is always /10 */
+       freq *= 10;
+
+       if (meson_hdmi_pll_find_params(priv, freq, &m, &frac, &od))
+               return MODE_OK;
+
+       return MODE_CLOCK_RANGE;
+}
+EXPORT_SYMBOL_GPL(meson_vclk_dmt_supported_freq);
+
+/* pll_freq is the frequency after the OD dividers */
+static void meson_hdmi_pll_generic_set(struct meson_drm *priv,
+                                      unsigned int pll_freq)
+{
+       unsigned int od, m, frac, od1, od2, od3;
+
+       if (meson_hdmi_pll_find_params(priv, pll_freq, &m, &frac, &od)) {
+               od3 = 1;
+               if (od < 4) {
+                       od1 = 2;
+                       od2 = 1;
+               } else {
+                       od2 = od / 4;
+                       od1 = od / od2;
+               }
+
+               DRM_DEBUG_DRIVER("PLL params for %dkHz: m=%x frac=%x od=%d/%d/%d\n",
+                                pll_freq, m, frac, od1, od2, od3);
+
+               meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
+
                return;
        }
 
+       DRM_ERROR("Fatal, unable to find parameters for PLL freq %d\n",
+                 pll_freq);
+}
+
+static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
+                          unsigned int od1, unsigned int od2, unsigned int od3,
+                          unsigned int vid_pll_div, unsigned int vclk_div,
+                          unsigned int hdmi_tx_div, unsigned int venc_div,
+                          bool hdmi_use_enci)
+{
        /* Set HDMI-TX sys clock */
        regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
                           CTS_HDMI_SYS_SEL_MASK, 0);
                           CTS_HDMI_SYS_EN, CTS_HDMI_SYS_EN);
 
        /* Set HDMI PLL rate */
-       meson_hdmi_pll_set(priv, params[freq].pll_base_freq,
-                          params[freq].pll_od1,
-                          params[freq].pll_od2,
-                          params[freq].pll_od3);
+       if (!od1 && !od2 && !od3) {
+               meson_hdmi_pll_generic_set(priv, pll_base_freq);
+       } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
+               switch (pll_base_freq) {
+               case 2970000:
+                       meson_hdmi_pll_set_params(priv, 0x3d, 0xe00,
+                                                 od1, od2, od3);
+                       break;
+               case 4320000:
+                       meson_hdmi_pll_set_params(priv, 0x5a, 0,
+                                                 od1, od2, od3);
+                       break;
+               case 5940000:
+                       meson_hdmi_pll_set_params(priv, 0x7b, 0xc00,
+                                                 od1, od2, od3);
+                       break;
+               }
+       } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
+                  meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
+               switch (pll_base_freq) {
+               case 2970000:
+                       meson_hdmi_pll_set_params(priv, 0x7b, 0x300,
+                                                 od1, od2, od3);
+                       break;
+               case 4320000:
+                       meson_hdmi_pll_set_params(priv, 0xb4, 0,
+                                                 od1, od2, od3);
+                       break;
+               case 5940000:
+                       meson_hdmi_pll_set_params(priv, 0xf7, 0x200,
+                                                 od1, od2, od3);
+                       break;
+               }
+       }
 
        /* Setup vid_pll divider */
-       meson_vid_pll_set(priv, params[freq].vid_pll_div);
+       meson_vid_pll_set(priv, vid_pll_div);
 
        /* Set VCLK div */
        regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
                           VCLK_SEL_MASK, 0);
        regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
-                          VCLK_DIV_MASK, params[freq].vclk_div - 1);
+                          VCLK_DIV_MASK, vclk_div - 1);
 
        /* Set HDMI-TX source */
        switch (hdmi_tx_div) {
 
        regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL, VCLK_EN, VCLK_EN);
 }
+
+void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
+                     unsigned int vclk_freq, unsigned int venc_freq,
+                     unsigned int dac_freq, bool hdmi_use_enci)
+{
+       unsigned int freq;
+       unsigned int hdmi_tx_div;
+       unsigned int venc_div;
+
+       if (target == MESON_VCLK_TARGET_CVBS) {
+               meson_venci_cvbs_clock_config(priv);
+               return;
+       } else if (target == MESON_VCLK_TARGET_DMT) {
+               /* The DMT clock path is fixed after the PLL:
+                * - automatic PLL freq + OD management
+                * - vid_pll_div = VID_PLL_DIV_5
+                * - vclk_div = 2
+                * - hdmi_tx_div = 1
+                * - venc_div = 1
+                * - encp encoder
+                */
+               meson_vclk_set(priv, vclk_freq * 10, 0, 0, 0,
+                              VID_PLL_DIV_5, 2, 1, 1, false);
+               return;
+       }
+
+       hdmi_tx_div = vclk_freq / dac_freq;
+
+       if (hdmi_tx_div == 0) {
+               pr_err("Fatal Error, invalid HDMI-TX freq %d\n",
+                      dac_freq);
+               return;
+       }
+
+       venc_div = vclk_freq / venc_freq;
+
+       if (venc_div == 0) {
+               pr_err("Fatal Error, invalid HDMI venc freq %d\n",
+                      venc_freq);
+               return;
+       }
+
+       switch (vclk_freq) {
+       case 54000:
+               if (hdmi_use_enci)
+                       freq = MESON_VCLK_HDMI_ENCI_54000;
+               else
+                       freq = MESON_VCLK_HDMI_DDR_54000;
+               break;
+       case 74250:
+               freq = MESON_VCLK_HDMI_74250;
+               break;
+       case 148500:
+               if (dac_freq != 148500)
+                       freq = MESON_VCLK_HDMI_DDR_148500;
+               else
+                       freq = MESON_VCLK_HDMI_148500;
+               break;
+       case 297000:
+               freq = MESON_VCLK_HDMI_297000;
+               break;
+       case 594000:
+               freq = MESON_VCLK_HDMI_594000;
+               break;
+       default:
+               pr_err("Fatal Error, invalid HDMI vclk freq %d\n",
+                      vclk_freq);
+               return;
+       }
+
+       meson_vclk_set(priv, params[freq].pll_base_freq,
+                      params[freq].pll_od1, params[freq].pll_od2,
+                      params[freq].pll_od3, params[freq].vid_pll_div,
+                      params[freq].vclk_div, hdmi_tx_div, venc_div,
+                      hdmi_use_enci);
+}
 EXPORT_SYMBOL_GPL(meson_vclk_setup);
 
        },
 };
 
-union meson_hdmi_venc_mode meson_hdmi_encp_mode_640x480_60 = {
-       .encp = {
-               .dvi_settings = 0x21,
-               .video_mode = 0x4040,
-               .video_mode_adv = 0x18,
-               /* video_prog_mode */
-               /* video_sync_mode */
-               /* video_yc_dly */
-               /* video_rgb_ctrl */
-               /* video_filt_ctrl */
-               /* video_ofld_voav_ofst */
-               /* yfp1_htime */
-               /* yfp2_htime */
-               .max_pxcnt = 0x31f,
-               /* hspuls_begin */
-               /* hspuls_end */
-               /* hspuls_switch */
-               /* vspuls_begin */
-               /* vspuls_end */
-               /* vspuls_bline */
-               /* vspuls_eline */
-               .havon_begin = 0x90,
-               .havon_end = 0x30f,
-               .vavon_bline = 0x23,
-               .vavon_eline = 0x202,
-               /* eqpuls_begin */
-               /* eqpuls_end */
-               /* eqpuls_bline */
-               /* eqpuls_eline */
-               .hso_begin = 0,
-               .hso_end = 0x60,
-               .vso_begin = 0x1e,
-               .vso_end = 0x32,
-               .vso_bline = 0,
-               .vso_eline = 2,
-               .vso_eline_present = true,
-               /* sy_val */
-               /* sy2_val */
-               .max_lncnt = 0x20c,
-       },
-};
-
-union meson_hdmi_venc_mode meson_hdmi_encp_mode_800x600_60 = {
-       .encp = {
-               .dvi_settings = 0x21,
-               .video_mode = 0x4040,
-               .video_mode_adv = 0x18,
-               /* video_prog_mode */
-               /* video_sync_mode */
-               /* video_yc_dly */
-               /* video_rgb_ctrl */
-               /* video_filt_ctrl */
-               /* video_ofld_voav_ofst */
-               /* yfp1_htime */
-               /* yfp2_htime */
-               .max_pxcnt = 0x41f,
-               /* hspuls_begin */
-               /* hspuls_end */
-               /* hspuls_switch */
-               /* vspuls_begin */
-               /* vspuls_end */
-               /* vspuls_bline */
-               /* vspuls_eline */
-               .havon_begin = 0xD8,
-               .havon_end = 0x3f7,
-               .vavon_bline = 0x1b,
-               .vavon_eline = 0x272,
-               /* eqpuls_begin */
-               /* eqpuls_end */
-               /* eqpuls_bline */
-               /* eqpuls_eline */
-               .hso_begin = 0,
-               .hso_end = 0x80,
-               .vso_begin = 0x1e,
-               .vso_end = 0x32,
-               .vso_bline = 0,
-               .vso_eline = 4,
-               .vso_eline_present = true,
-               /* sy_val */
-               /* sy2_val */
-               .max_lncnt = 0x273,
-       },
-};
-
-union meson_hdmi_venc_mode meson_hdmi_encp_mode_1024x768_60 = {
-       .encp = {
-               .dvi_settings = 0x21,
-               .video_mode = 0x4040,
-               .video_mode_adv = 0x18,
-               /* video_prog_mode */
-               /* video_sync_mode */
-               /* video_yc_dly */
-               /* video_rgb_ctrl */
-               /* video_filt_ctrl */
-               /* video_ofld_voav_ofst */
-               /* yfp1_htime */
-               /* yfp2_htime */
-               .max_pxcnt = 1343,
-               /* hspuls_begin */
-               /* hspuls_end */
-               /* hspuls_switch */
-               /* vspuls_begin */
-               /* vspuls_end */
-               /* vspuls_bline */
-               /* vspuls_eline */
-               .havon_begin = 296,
-               .havon_end = 1319,
-               .vavon_bline = 35,
-               .vavon_eline = 802,
-               /* eqpuls_begin */
-               /* eqpuls_end */
-               /* eqpuls_bline */
-               /* eqpuls_eline */
-               .hso_begin = 0,
-               .hso_end = 136,
-               .vso_begin = 30,
-               .vso_end = 50,
-               .vso_bline = 0,
-               .vso_eline = 6,
-               .vso_eline_present = true,
-               /* sy_val */
-               /* sy2_val */
-               .max_lncnt = 805,
-       },
-};
-
-union meson_hdmi_venc_mode meson_hdmi_encp_mode_1152x864_75 = {
-       .encp = {
-               .dvi_settings = 0x21,
-               .video_mode = 0x4040,
-               .video_mode_adv = 0x18,
-               /* video_prog_mode */
-               /* video_sync_mode */
-               /* video_yc_dly */
-               /* video_rgb_ctrl */
-               /* video_filt_ctrl */
-               /* video_ofld_voav_ofst */
-               /* yfp1_htime */
-               /* yfp2_htime */
-               .max_pxcnt = 0x63f,
-               /* hspuls_begin */
-               /* hspuls_end */
-               /* hspuls_switch */
-               /* vspuls_begin */
-               /* vspuls_end */
-               /* vspuls_bline */
-               /* vspuls_eline */
-               .havon_begin = 0x180,
-               .havon_end = 0x5ff,
-               .vavon_bline = 0x23,
-               .vavon_eline = 0x382,
-               /* eqpuls_begin */
-               /* eqpuls_end */
-               /* eqpuls_bline */
-               /* eqpuls_eline */
-               .hso_begin = 0,
-               .hso_end = 0x80,
-               .vso_begin = 0x1e,
-               .vso_end = 0x32,
-               .vso_bline = 0,
-               .vso_eline = 3,
-               .vso_eline_present = true,
-               /* sy_val */
-               /* sy2_val */
-               .max_lncnt = 0x383,
-       },
-};
-
-union meson_hdmi_venc_mode meson_hdmi_encp_mode_1280x1024_60 = {
-       .encp = {
-               .dvi_settings = 0x21,
-               .video_mode = 0x4040,
-               .video_mode_adv = 0x18,
-               /* video_prog_mode */
-               /* video_sync_mode */
-               /* video_yc_dly */
-               /* video_rgb_ctrl */
-               /* video_filt_ctrl */
-               /* video_ofld_voav_ofst */
-               /* yfp1_htime */
-               /* yfp2_htime */
-               .max_pxcnt = 0x697,
-               /* hspuls_begin */
-               /* hspuls_end */
-               /* hspuls_switch */
-               /* vspuls_begin */
-               /* vspuls_end */
-               /* vspuls_bline */
-               /* vspuls_eline */
-               .havon_begin = 0x168,
-               .havon_end = 0x667,
-               .vavon_bline = 0x29,
-               .vavon_eline = 0x428,
-               /* eqpuls_begin */
-               /* eqpuls_end */
-               /* eqpuls_bline */
-               /* eqpuls_eline */
-               .hso_begin = 0,
-               .hso_end = 0x70,
-               .vso_begin = 0x1e,
-               .vso_end = 0x32,
-               .vso_bline = 0,
-               .vso_eline = 3,
-               .vso_eline_present = true,
-               /* sy_val */
-               /* sy2_val */
-               .max_lncnt = 0x429,
-       },
-};
-
-union meson_hdmi_venc_mode meson_hdmi_encp_mode_1600x1200_60 = {
-       .encp = {
-               .dvi_settings = 0x21,
-               .video_mode = 0x4040,
-               .video_mode_adv = 0x18,
-               /* video_prog_mode */
-               /* video_sync_mode */
-               /* video_yc_dly */
-               /* video_rgb_ctrl */
-               /* video_filt_ctrl */
-               /* video_ofld_voav_ofst */
-               /* yfp1_htime */
-               /* yfp2_htime */
-               .max_pxcnt = 0x86f,
-               /* hspuls_begin */
-               /* hspuls_end */
-               /* hspuls_switch */
-               /* vspuls_begin */
-               /* vspuls_end */
-               /* vspuls_bline */
-               /* vspuls_eline */
-               .havon_begin = 0x1f0,
-               .havon_end = 0x82f,
-               .vavon_bline = 0x31,
-               .vavon_eline = 0x4e0,
-               /* eqpuls_begin */
-               /* eqpuls_end */
-               /* eqpuls_bline */
-               /* eqpuls_eline */
-               .hso_begin = 0,
-               .hso_end = 0xc0,
-               .vso_begin = 0x1e,
-               .vso_end = 0x32,
-               .vso_bline = 0,
-               .vso_eline = 3,
-               .vso_eline_present = true,
-               /* sy_val */
-               /* sy2_val */
-               .max_lncnt = 0x4e1,
-       },
-};
-
-struct meson_hdmi_venc_dmt_mode {
-       struct drm_display_mode drm_mode;
-       union meson_hdmi_venc_mode *mode;
-} meson_hdmi_venc_dmt_modes[] = {
-       /* 640x480@60Hz */
-       {
-               { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
-                 752, 800, 0, 480, 490, 492, 525, 0,
-                 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
-               &meson_hdmi_encp_mode_640x480_60,
-       },
-       /* 800x600@60Hz */
-       {
-               { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
-                 968, 1056, 0, 600, 601, 605, 628, 0,
-                 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-               &meson_hdmi_encp_mode_800x600_60,
-       },
-       /* 1024x768@60Hz */
-       {
-               { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024,
-                 1048, 1184, 1344, 0, 768, 771, 777, 806, 0,
-                 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
-               &meson_hdmi_encp_mode_1024x768_60,
-       },
-       /* 1152x864@75Hz */
-       {
-               { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152,
-                 1216, 1344, 1600, 0, 864, 865, 868, 900, 0,
-                 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-               &meson_hdmi_encp_mode_1152x864_75,
-       },
-       /* 1280x1024@60Hz */
-       {
-               { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280,
-                 1328, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
-                 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-               &meson_hdmi_encp_mode_1280x1024_60,
-       },
-       /* 1600x1200@60Hz */
-       {
-               { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600,
-                 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
-                 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-               &meson_hdmi_encp_mode_1600x1200_60,
-       },
-       /* 1920x1080@60Hz */
-       {
-               { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920,
-                 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
-                 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
-               &meson_hdmi_encp_mode_1080p60
-       },
-       { }, /* sentinel */
-};
-
 struct meson_hdmi_venc_vic_mode {
        unsigned int vic;
        union meson_hdmi_venc_mode *mode;
                return a;
 }
 
-bool meson_venc_hdmi_supported_mode(const struct drm_display_mode *mode)
+enum drm_mode_status
+meson_venc_hdmi_supported_mode(const struct drm_display_mode *mode)
 {
-       struct meson_hdmi_venc_dmt_mode *vmode = meson_hdmi_venc_dmt_modes;
+       if (mode->flags & ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC |
+                           DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC))
+               return MODE_BAD;
 
-       while (vmode->mode) {
-               if (drm_mode_equal(&vmode->drm_mode, mode))
-                       return true;
-               vmode++;
-       }
+       if (mode->hdisplay < 640 || mode->hdisplay > 1920)
+               return MODE_BAD_HVALUE;
 
-       return false;
+       if (mode->vdisplay < 480 || mode->vdisplay > 1200)
+               return MODE_BAD_VVALUE;
+
+       return MODE_OK;
 }
 EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_mode);
 
 }
 EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_vic);
 
-static union meson_hdmi_venc_mode
-*meson_venc_hdmi_get_dmt_vmode(const struct drm_display_mode *mode)
+void meson_venc_hdmi_get_dmt_vmode(const struct drm_display_mode *mode,
+                                  union meson_hdmi_venc_mode *dmt_mode)
 {
-       struct meson_hdmi_venc_dmt_mode *vmode = meson_hdmi_venc_dmt_modes;
-
-       while (vmode->mode) {
-               if (drm_mode_equal(&vmode->drm_mode, mode))
-                       return vmode->mode;
-               vmode++;
-       }
-
-       return NULL;
+       memset(dmt_mode, 0, sizeof(*dmt_mode));
+
+       dmt_mode->encp.dvi_settings = 0x21;
+       dmt_mode->encp.video_mode = 0x4040;
+       dmt_mode->encp.video_mode_adv = 0x18;
+       dmt_mode->encp.max_pxcnt = mode->htotal - 1;
+       dmt_mode->encp.havon_begin = mode->htotal - mode->hsync_start;
+       dmt_mode->encp.havon_end = dmt_mode->encp.havon_begin +
+                                  mode->hdisplay - 1;
+       dmt_mode->encp.vavon_bline = mode->vtotal - mode->vsync_start;
+       dmt_mode->encp.vavon_eline = dmt_mode->encp.vavon_bline +
+                                    mode->vdisplay - 1;
+       dmt_mode->encp.hso_begin = 0;
+       dmt_mode->encp.hso_end = mode->hsync_end - mode->hsync_start;
+       dmt_mode->encp.vso_begin = 30;
+       dmt_mode->encp.vso_end = 50;
+       dmt_mode->encp.vso_bline = 0;
+       dmt_mode->encp.vso_eline = mode->vsync_end - mode->vsync_start;
+       dmt_mode->encp.vso_eline_present = true;
+       dmt_mode->encp.max_lncnt = mode->vtotal - 1;
 }
 
 static union meson_hdmi_venc_mode *meson_venc_hdmi_get_vic_vmode(int vic)
                              struct drm_display_mode *mode)
 {
        union meson_hdmi_venc_mode *vmode = NULL;
+       union meson_hdmi_venc_mode vmode_dmt;
        bool use_enci = false;
        bool venc_repeat = false;
        bool hdmi_repeat = false;
        unsigned int sof_lines;
        unsigned int vsync_lines;
 
-       if (meson_venc_hdmi_supported_vic(vic))
+       if (meson_venc_hdmi_supported_vic(vic)) {
                vmode = meson_venc_hdmi_get_vic_vmode(vic);
-       else
-               vmode = meson_venc_hdmi_get_dmt_vmode(mode);
-       if (!vmode) {
-               dev_err(priv->dev, "%s: Fatal Error, unsupported mode "
-                       DRM_MODE_FMT "\n", __func__, DRM_MODE_ARG(mode));
-               return;
+               if (!vmode) {
+                       dev_err(priv->dev, "%s: Fatal Error, unsupported mode "
+                               DRM_MODE_FMT "\n", __func__,
+                               DRM_MODE_ARG(mode));
+                       return;
+               }
+       } else {
+               meson_venc_hdmi_get_dmt_vmode(mode, &vmode_dmt);
+               vmode = &vmode_dmt;
        }
 
        /* Use VENCI for 480i and 576i and double HDMI pixels */