summaryrefslogtreecommitdiffstats
path: root/drivers/video/fbdev/omap2/dss/hdmi_pll.c
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2014-10-22 15:02:17 +0300
committerTomi Valkeinen <tomi.valkeinen@ti.com>2014-11-12 13:40:27 +0200
commitc84c3a5bb78ff271787a1fec9218768aed555e8d (patch)
tree98c64021765bcaf1b5389a9082ae98487c7f9c2b /drivers/video/fbdev/omap2/dss/hdmi_pll.c
parentd13cbb32c50019b38fb3ab030a8ab435b6f2440a (diff)
downloadop-kernel-dev-c84c3a5bb78ff271787a1fec9218768aed555e8d.zip
op-kernel-dev-c84c3a5bb78ff271787a1fec9218768aed555e8d.tar.gz
OMAPDSS: HDMI: use common DSS PLL support
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>
Diffstat (limited to 'drivers/video/fbdev/omap2/dss/hdmi_pll.c')
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi_pll.c225
1 files changed, 104 insertions, 121 deletions
diff --git a/drivers/video/fbdev/omap2/dss/hdmi_pll.c b/drivers/video/fbdev/omap2/dss/hdmi_pll.c
index 92d2225..87accdb 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi_pll.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi_pll.c
@@ -15,22 +15,13 @@
#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);
+}
OpenPOWER on IntegriCloud