OMAPDSS: HDMI: use common DSS PLL support
authorTomi Valkeinen <tomi.valkeinen@ti.com>
Wed, 22 Oct 2014 12:02:17 +0000 (15:02 +0300)
committerTomi Valkeinen <tomi.valkeinen@ti.com>
Wed, 12 Nov 2014 11:40:27 +0000 (13:40 +0200)
Now that we have the common DSS PLL support, change HDMI to use it. This
results in quite a lot of changes, but almost all of them are trivial
name changes.

The function to program the PLL settings can be removed from hdmi_pll.c,
as the common PLL API contains the same functionality.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
drivers/video/fbdev/omap2/dss/hdmi.h
drivers/video/fbdev/omap2/dss/hdmi4.c
drivers/video/fbdev/omap2/dss/hdmi5.c
drivers/video/fbdev/omap2/dss/hdmi_pll.c

index 7595274a9bcf25c21e0df0d5c2fc0d9df06259cd..3c42823e934bf9d446dd9d1249b549f839fb3262 100644 (file)
@@ -184,18 +184,6 @@ struct hdmi_config {
        enum hdmi_core_hdmi_dvi hdmi_dvi_mode;
 };
 
-/* HDMI PLL structure */
-struct hdmi_pll_info {
-       u16 regn;
-       u16 regm;
-       u32 regmf;
-       u16 regm2;
-       u16 regsd;
-
-       unsigned long clkdco;
-       unsigned long clkout;
-};
-
 struct hdmi_audio_format {
        enum hdmi_stereo_channels               stereo_channels;
        u8                                      active_chnnls_msk;
@@ -246,11 +234,11 @@ struct hdmi_wp_data {
 };
 
 struct hdmi_pll_data {
+       struct dss_pll pll;
+
        void __iomem *base;
 
        struct hdmi_wp_data *wp;
-
-       struct hdmi_pll_info info;
 };
 
 struct hdmi_phy_data {
@@ -314,14 +302,12 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
 int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp);
 
 /* HDMI PLL funcs */
-int hdmi_pll_enable(struct hdmi_pll_data *pll);
-void hdmi_pll_disable(struct hdmi_pll_data *pll);
-int hdmi_pll_set_config(struct hdmi_pll_data *pll);
 void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s);
-void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin,
-       unsigned long target_tmds);
+void hdmi_pll_compute(struct hdmi_pll_data *pll,
+       unsigned long target_tmds, struct dss_pll_clock_info *pi);
 int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll,
        struct hdmi_wp_data *wp);
+void hdmi_pll_uninit(struct hdmi_pll_data *hpll);
 
 /* HDMI PHY funcs */
 int hdmi_phy_configure(struct hdmi_phy_data *phy, unsigned long hfbitclk,
index 98aa910241b818ed0a1b117c074feea3c8803e6c..46dcc71ce05858204c99abc56a0c9286a9c51f27 100644 (file)
@@ -49,7 +49,6 @@ static struct {
 
        struct hdmi_config cfg;
 
-       struct clk *sys_clk;
        struct regulator *vdda_hdmi_dac_reg;
 
        bool core_enabled;
@@ -181,6 +180,7 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
        struct omap_video_timings *p;
        struct omap_overlay_manager *mgr = hdmi.output.manager;
        struct hdmi_wp_data *wp = &hdmi.wp;
+       struct dss_pll_clock_info hdmi_cinfo = { 0 };
 
        r = hdmi_power_on_core(dssdev);
        if (r)
@@ -194,22 +194,22 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
 
        DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
 
-       hdmi_pll_compute(&hdmi.pll, clk_get_rate(hdmi.sys_clk), p->pixelclock);
+       hdmi_pll_compute(&hdmi.pll, p->pixelclock, &hdmi_cinfo);
 
-       r = hdmi_pll_enable(&hdmi.pll);
+       r = dss_pll_enable(&hdmi.pll.pll);
        if (r) {
                DSSERR("Failed to enable PLL\n");
                goto err_pll_enable;
        }
 
-       r = hdmi_pll_set_config(&hdmi.pll);
+       r = dss_pll_set_config(&hdmi.pll.pll, &hdmi_cinfo);
        if (r) {
                DSSERR("Failed to configure PLL\n");
                goto err_pll_cfg;
        }
 
-       r = hdmi_phy_configure(&hdmi.phy, hdmi.pll.info.clkdco,
-               hdmi.pll.info.clkout);
+       r = hdmi_phy_configure(&hdmi.phy, hdmi_cinfo.clkdco,
+               hdmi_cinfo.clkout[0]);
        if (r) {
                DSSDBG("Failed to configure PHY\n");
                goto err_phy_cfg;
@@ -247,7 +247,7 @@ err_phy_cfg:
        hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
 err_phy_pwr:
 err_pll_cfg:
-       hdmi_pll_disable(&hdmi.pll);
+       dss_pll_disable(&hdmi.pll.pll);
 err_pll_enable:
        hdmi_power_off_core(dssdev);
        return -EIO;
@@ -265,7 +265,7 @@ static void hdmi_power_off_full(struct omap_dss_device *dssdev)
 
        hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
 
-       hdmi_pll_disable(&hdmi.pll);
+       dss_pll_disable(&hdmi.pll.pll);
 
        hdmi_power_off_core(dssdev);
 }
@@ -407,21 +407,6 @@ static void hdmi_core_disable(struct omap_dss_device *dssdev)
        mutex_unlock(&hdmi.lock);
 }
 
-static int hdmi_get_clocks(struct platform_device *pdev)
-{
-       struct clk *clk;
-
-       clk = devm_clk_get(&pdev->dev, "sys_clk");
-       if (IS_ERR(clk)) {
-               DSSERR("can't get sys_clk\n");
-               return PTR_ERR(clk);
-       }
-
-       hdmi.sys_clk = clk;
-
-       return 0;
-}
-
 static int hdmi_connect(struct omap_dss_device *dssdev,
                struct omap_dss_device *dst)
 {
@@ -700,22 +685,17 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
 
        r = hdmi_phy_init(pdev, &hdmi.phy);
        if (r)
-               return r;
+               goto err;
 
        r = hdmi4_core_init(pdev, &hdmi.core);
        if (r)
-               return r;
-
-       r = hdmi_get_clocks(pdev);
-       if (r) {
-               DSSERR("can't get clocks\n");
-               return r;
-       }
+               goto err;
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                DSSERR("platform_get_irq failed\n");
-               return -ENODEV;
+               r = -ENODEV;
+               goto err;
        }
 
        r = devm_request_threaded_irq(&pdev->dev, irq,
@@ -723,7 +703,7 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
                        IRQF_ONESHOT, "OMAP HDMI", &hdmi.wp);
        if (r) {
                DSSERR("HDMI IRQ request failed\n");
-               return r;
+               goto err;
        }
 
        pm_runtime_enable(&pdev->dev);
@@ -733,12 +713,17 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
        dss_debugfs_create_file("hdmi", hdmi_dump_regs);
 
        return 0;
+err:
+       hdmi_pll_uninit(&hdmi.pll);
+       return r;
 }
 
 static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
 {
        hdmi_uninit_output(pdev);
 
+       hdmi_pll_uninit(&hdmi.pll);
+
        pm_runtime_disable(&pdev->dev);
 
        return 0;
@@ -746,8 +731,6 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
 
 static int hdmi_runtime_suspend(struct device *dev)
 {
-       clk_disable_unprepare(hdmi.sys_clk);
-
        dispc_runtime_put();
 
        return 0;
@@ -761,8 +744,6 @@ static int hdmi_runtime_resume(struct device *dev)
        if (r < 0)
                return r;
 
-       clk_prepare_enable(hdmi.sys_clk);
-
        return 0;
 }
 
index facc4e070520ae1cb87d084120d241ada7c74473..67facf87b3707247e6f124efc5b1ac19a8031b3d 100644 (file)
@@ -54,8 +54,8 @@ static struct {
 
        struct hdmi_config cfg;
 
-       struct clk *sys_clk;
        struct regulator *vdda_reg;
+       struct clk *sys_clk;
 
        bool core_enabled;
 
@@ -198,6 +198,7 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
        int r;
        struct omap_video_timings *p;
        struct omap_overlay_manager *mgr = hdmi.output.manager;
+       struct dss_pll_clock_info hdmi_cinfo = { 0 };
 
        r = hdmi_power_on_core(dssdev);
        if (r)
@@ -207,27 +208,27 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
 
        DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
 
-       hdmi_pll_compute(&hdmi.pll, clk_get_rate(hdmi.sys_clk), p->pixelclock);
+       hdmi_pll_compute(&hdmi.pll, p->pixelclock, &hdmi_cinfo);
 
        /* disable and clear irqs */
        hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff);
        hdmi_wp_set_irqstatus(&hdmi.wp,
                        hdmi_wp_get_irqstatus(&hdmi.wp));
 
-       r = hdmi_pll_enable(&hdmi.pll);
+       r = dss_pll_enable(&hdmi.pll.pll);
        if (r) {
                DSSERR("Failed to enable PLL\n");
                goto err_pll_enable;
        }
 
-       r = hdmi_pll_set_config(&hdmi.pll);
+       r = dss_pll_set_config(&hdmi.pll.pll, &hdmi_cinfo);
        if (r) {
                DSSERR("Failed to configure PLL\n");
                goto err_pll_cfg;
        }
 
-       r = hdmi_phy_configure(&hdmi.phy, hdmi.pll.info.clkdco,
-               hdmi.pll.info.clkout);
+       r = hdmi_phy_configure(&hdmi.phy, hdmi_cinfo.clkdco,
+               hdmi_cinfo.clkout[0]);
        if (r) {
                DSSDBG("Failed to start PHY\n");
                goto err_phy_cfg;
@@ -265,7 +266,7 @@ err_vid_enable:
 err_phy_pwr:
 err_phy_cfg:
 err_pll_cfg:
-       hdmi_pll_disable(&hdmi.pll);
+       dss_pll_disable(&hdmi.pll.pll);
 err_pll_enable:
        hdmi_power_off_core(dssdev);
        return -EIO;
@@ -283,7 +284,7 @@ static void hdmi_power_off_full(struct omap_dss_device *dssdev)
 
        hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
 
-       hdmi_pll_disable(&hdmi.pll);
+       dss_pll_disable(&hdmi.pll.pll);
 
        hdmi_power_off_core(dssdev);
 }
@@ -436,21 +437,6 @@ static void hdmi_core_disable(struct omap_dss_device *dssdev)
        mutex_unlock(&hdmi.lock);
 }
 
-static int hdmi_get_clocks(struct platform_device *pdev)
-{
-       struct clk *clk;
-
-       clk = devm_clk_get(&pdev->dev, "sys_clk");
-       if (IS_ERR(clk)) {
-               DSSERR("can't get sys_clk\n");
-               return PTR_ERR(clk);
-       }
-
-       hdmi.sys_clk = clk;
-
-       return 0;
-}
-
 static int hdmi_connect(struct omap_dss_device *dssdev,
                struct omap_dss_device *dst)
 {
@@ -729,22 +715,17 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
 
        r = hdmi_phy_init(pdev, &hdmi.phy);
        if (r)
-               return r;
+               goto err;
 
        r = hdmi5_core_init(pdev, &hdmi.core);
        if (r)
-               return r;
-
-       r = hdmi_get_clocks(pdev);
-       if (r) {
-               DSSERR("can't get clocks\n");
-               return r;
-       }
+               goto err;
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                DSSERR("platform_get_irq failed\n");
-               return -ENODEV;
+               r = -ENODEV;
+               goto err;
        }
 
        r = devm_request_threaded_irq(&pdev->dev, irq,
@@ -752,7 +733,7 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
                        IRQF_ONESHOT, "OMAP HDMI", &hdmi.wp);
        if (r) {
                DSSERR("HDMI IRQ request failed\n");
-               return r;
+               goto err;
        }
 
        pm_runtime_enable(&pdev->dev);
@@ -762,12 +743,17 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
        dss_debugfs_create_file("hdmi", hdmi_dump_regs);
 
        return 0;
+err:
+       hdmi_pll_uninit(&hdmi.pll);
+       return r;
 }
 
 static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
 {
        hdmi_uninit_output(pdev);
 
+       hdmi_pll_uninit(&hdmi.pll);
+
        pm_runtime_disable(&pdev->dev);
 
        return 0;
@@ -775,8 +761,6 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
 
 static int hdmi_runtime_suspend(struct device *dev)
 {
-       clk_disable_unprepare(hdmi.sys_clk);
-
        dispc_runtime_put();
 
        return 0;
@@ -790,8 +774,6 @@ static int hdmi_runtime_resume(struct device *dev)
        if (r < 0)
                return r;
 
-       clk_prepare_enable(hdmi.sys_clk);
-
        return 0;
 }
 
index 92d22252f86a91e67f0b58225660e61cea33fb58..87accdb59c81b5ed5686ad2c291c636fe541289a 100644 (file)
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
+#include <linux/clk.h>
+
 #include <video/omapdss.h>
 
 #include "dss.h"
 #include "hdmi.h"
 
-struct hdmi_pll_features {
-       bool has_refsel;
-       bool sys_reset;
-       unsigned long fint_min, fint_max;
-       u16 regm_max;
-       unsigned long dcofreq_low_min, dcofreq_low_max;
-       unsigned long dcofreq_high_min, dcofreq_high_max;
-};
-
-static const struct hdmi_pll_features *pll_feat;
-
 void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s)
 {
 #define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\
@@ -47,25 +38,28 @@ void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s)
        DUMPPLL(PLLCTRL_CFG4);
 }
 
-void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin,
-       unsigned long target_tmds)
+void hdmi_pll_compute(struct hdmi_pll_data *pll,
+       unsigned long target_tmds, struct dss_pll_clock_info *pi)
 {
-       struct hdmi_pll_info *pi = &pll->info;
        unsigned long fint, clkdco, clkout;
        unsigned long target_bitclk, target_clkdco;
        unsigned long min_dco;
        unsigned n, m, mf, m2, sd;
+       unsigned long clkin;
+       const struct dss_pll_hw *hw = pll->pll.hw;
+
+       clkin = clk_get_rate(pll->pll.clkin);
 
        DSSDBG("clkin %lu, target tmds %lu\n", clkin, target_tmds);
 
        target_bitclk = target_tmds * 10;
 
        /* Fint */
-       n = DIV_ROUND_UP(clkin, pll_feat->fint_max);
+       n = DIV_ROUND_UP(clkin, hw->fint_max);
        fint = clkin / n;
 
        /* adjust m2 so that the clkdco will be high enough */
-       min_dco = roundup(pll_feat->dcofreq_low_min, fint);
+       min_dco = roundup(hw->clkdco_min, fint);
        m2 = DIV_ROUND_UP(min_dco, target_bitclk);
        if (m2 == 0)
                m2 = 1;
@@ -93,81 +87,20 @@ void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin,
                n, m, mf, m2, sd);
        DSSDBG("Fint %lu, clkdco %lu, clkout %lu\n", fint, clkdco, clkout);
 
-       pi->regn = n;
-       pi->regm = m;
-       pi->regmf = mf;
-       pi->regm2 = m2;
-       pi->regsd = sd;
+       pi->n = n;
+       pi->m = m;
+       pi->mf = mf;
+       pi->mX[0] = m2;
+       pi->sd = sd;
 
+       pi->fint = fint;
        pi->clkdco = clkdco;
-       pi->clkout = clkout;
-}
-
-int hdmi_pll_set_config(struct hdmi_pll_data *pll)
-{
-       u32 r;
-       struct hdmi_pll_info *fmt = &pll->info;
-
-       /* PLL start always use manual mode */
-       REG_FLD_MOD(pll->base, PLLCTRL_PLL_CONTROL, 0x0, 0, 0);
-
-       r = hdmi_read_reg(pll->base, PLLCTRL_CFG1);
-       r = FLD_MOD(r, fmt->regm, 20, 9);       /* CFG1_PLL_REGM */
-       r = FLD_MOD(r, fmt->regn - 1, 8, 1);    /* CFG1_PLL_REGN */
-       hdmi_write_reg(pll->base, PLLCTRL_CFG1, r);
-
-       r = hdmi_read_reg(pll->base, PLLCTRL_CFG2);
-
-       r = FLD_MOD(r, 0x0, 12, 12);    /* PLL_HIGHFREQ divide by 2 */
-       r = FLD_MOD(r, 0x1, 13, 13);    /* PLL_REFEN */
-       r = FLD_MOD(r, 0x0, 14, 14);    /* PHY_CLKINEN de-assert during locking */
-       if (pll_feat->has_refsel)
-               r = FLD_MOD(r, 0x3, 22, 21);    /* REFSEL = SYSCLK */
-
-       if (fmt->clkdco > pll_feat->dcofreq_low_max)
-               r = FLD_MOD(r, 0x4, 3, 1);      /* 1000MHz and 2000MHz */
-       else
-               r = FLD_MOD(r, 0x2, 3, 1);      /* 500MHz and 1000MHz */
-
-       hdmi_write_reg(pll->base, PLLCTRL_CFG2, r);
-
-       REG_FLD_MOD(pll->base, PLLCTRL_CFG3, fmt->regsd, 17, 10);
-
-       r = hdmi_read_reg(pll->base, PLLCTRL_CFG4);
-       r = FLD_MOD(r, fmt->regm2, 24, 18);
-       r = FLD_MOD(r, fmt->regmf, 17, 0);
-       hdmi_write_reg(pll->base, PLLCTRL_CFG4, r);
-
-       /* go now */
-       REG_FLD_MOD(pll->base, PLLCTRL_PLL_GO, 0x1, 0, 0);
-
-       /* wait for bit change */
-       if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_GO,
-                       0, 0, 0) != 0) {
-               DSSERR("PLL GO bit not clearing\n");
-               return -ETIMEDOUT;
-       }
-
-       /* Wait till the lock bit is set in PLL status */
-       if (hdmi_wait_for_bit_change(pll->base,
-                       PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) {
-               DSSERR("cannot lock PLL\n");
-               DSSERR("CFG1 0x%x\n",
-                       hdmi_read_reg(pll->base, PLLCTRL_CFG1));
-               DSSERR("CFG2 0x%x\n",
-                       hdmi_read_reg(pll->base, PLLCTRL_CFG2));
-               DSSERR("CFG4 0x%x\n",
-                       hdmi_read_reg(pll->base, PLLCTRL_CFG4));
-               return -ETIMEDOUT;
-       }
-
-       DSSDBG("PLL locked!\n");
-
-       return 0;
+       pi->clkout[0] = clkout;
 }
 
-int hdmi_pll_enable(struct hdmi_pll_data *pll)
+static int hdmi_pll_enable(struct dss_pll *dsspll)
 {
+       struct hdmi_pll_data *pll = container_of(dsspll, struct hdmi_pll_data, pll);
        struct hdmi_wp_data *wp = pll->wp;
        u16 r = 0;
 
@@ -178,64 +111,105 @@ int hdmi_pll_enable(struct hdmi_pll_data *pll)
        return 0;
 }
 
-void hdmi_pll_disable(struct hdmi_pll_data *pll)
+static void hdmi_pll_disable(struct dss_pll *dsspll)
 {
+       struct hdmi_pll_data *pll = container_of(dsspll, struct hdmi_pll_data, pll);
        struct hdmi_wp_data *wp = pll->wp;
 
        hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF);
 }
 
-static const struct hdmi_pll_features omap44xx_pll_feats = {
-       .sys_reset              =       false,
-       .fint_min               =       500000,
-       .fint_max               =       2500000,
-       .regm_max               =       4095,
-       .dcofreq_low_min        =       500000000,
-       .dcofreq_low_max        =       1000000000,
-       .dcofreq_high_min       =       1000000000,
-       .dcofreq_high_max       =       2000000000,
+static const struct dss_pll_ops dsi_pll_ops = {
+       .enable = hdmi_pll_enable,
+       .disable = hdmi_pll_disable,
+       .set_config = dss_pll_write_config_type_b,
+};
+
+static const struct dss_pll_hw dss_omap4_hdmi_pll_hw = {
+       .n_max = 255,
+       .m_min = 20,
+       .m_max = 4095,
+       .mX_max = 127,
+       .fint_min = 500000,
+       .fint_max = 2500000,
+       .clkdco_max = 1800000000,
+
+       .clkdco_min = 500000000,
+       .clkdco_low = 1000000000,
+       .clkdco_max = 2000000000,
+
+       .n_msb = 8,
+       .n_lsb = 1,
+       .m_msb = 20,
+       .m_lsb = 9,
+
+       .mX_msb[0] = 24,
+       .mX_lsb[0] = 18,
+
+       .has_selfreqdco = true,
 };
 
-static const struct hdmi_pll_features omap54xx_pll_feats = {
-       .has_refsel             =       true,
-       .sys_reset              =       true,
-       .fint_min               =       620000,
-       .fint_max               =       2500000,
-       .regm_max               =       2046,
-       .dcofreq_low_min        =       750000000,
-       .dcofreq_low_max        =       1500000000,
-       .dcofreq_high_min       =       1250000000,
-       .dcofreq_high_max       =       2500000000UL,
+static const struct dss_pll_hw dss_omap5_hdmi_pll_hw = {
+       .n_max = 255,
+       .m_min = 20,
+       .m_max = 2045,
+       .mX_max = 127,
+       .fint_min = 620000,
+       .fint_max = 2500000,
+       .clkdco_max = 1800000000,
+
+       .clkdco_min = 750000000,
+       .clkdco_low = 1500000000,
+       .clkdco_max = 2500000000UL,
+
+       .n_msb = 8,
+       .n_lsb = 1,
+       .m_msb = 20,
+       .m_lsb = 9,
+
+       .mX_msb[0] = 24,
+       .mX_lsb[0] = 18,
+
+       .has_selfreqdco = true,
+       .has_refsel = true,
 };
 
-static int hdmi_pll_init_features(struct platform_device *pdev)
+static int dsi_init_pll_data(struct platform_device *pdev, struct hdmi_pll_data *hpll)
 {
-       struct hdmi_pll_features *dst;
-       const struct hdmi_pll_features *src;
+       struct dss_pll *pll = &hpll->pll;
+       struct clk *clk;
+       int r;
 
-       dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
-       if (!dst) {
-               dev_err(&pdev->dev, "Failed to allocate HDMI PHY Features\n");
-               return -ENOMEM;
+       clk = devm_clk_get(&pdev->dev, "sys_clk");
+       if (IS_ERR(clk)) {
+               DSSERR("can't get sys_clk\n");
+               return PTR_ERR(clk);
        }
 
+       pll->name = "hdmi";
+       pll->base = hpll->base;
+       pll->clkin = clk;
+
        switch (omapdss_get_version()) {
        case OMAPDSS_VER_OMAP4430_ES1:
        case OMAPDSS_VER_OMAP4430_ES2:
        case OMAPDSS_VER_OMAP4:
-               src = &omap44xx_pll_feats;
+               pll->hw = &dss_omap4_hdmi_pll_hw;
                break;
 
        case OMAPDSS_VER_OMAP5:
-               src = &omap54xx_pll_feats;
+               pll->hw = &dss_omap5_hdmi_pll_hw;
                break;
 
        default:
                return -ENODEV;
        }
 
-       memcpy(dst, src, sizeof(*dst));
-       pll_feat = dst;
+       pll->ops = &dsi_pll_ops;
+
+       r = dss_pll_register(pll);
+       if (r)
+               return r;
 
        return 0;
 }
@@ -248,10 +222,6 @@ int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll,
 
        pll->wp = wp;
 
-       r = hdmi_pll_init_features(pdev);
-       if (r)
-               return r;
-
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll");
        if (!res) {
                DSSERR("can't get PLL mem resource\n");
@@ -264,5 +234,18 @@ int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll,
                return PTR_ERR(pll->base);
        }
 
+       r = dsi_init_pll_data(pdev, pll);
+       if (r) {
+               DSSERR("failed to init HDMI PLL\n");
+               return r;
+       }
+
        return 0;
 }
+
+void hdmi_pll_uninit(struct hdmi_pll_data *hpll)
+{
+       struct dss_pll *pll = &hpll->pll;
+
+       dss_pll_unregister(pll);
+}