Merge branch '4.8/omapdrm-pll' (omapdrm PLL work)

Merge omapdrm PLL work, which makes it possible to use the DSS PLLs in a
versatile manner, for example, HDMI PLL can be used for LCDs.
This commit is contained in:
Tomi Valkeinen 2016-06-06 10:16:51 +03:00
commit ecf140dfc3
16 changed files with 509 additions and 373 deletions

View File

@ -3299,30 +3299,21 @@ static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div,
static unsigned long dispc_fclk_rate(void) static unsigned long dispc_fclk_rate(void)
{ {
struct dss_pll *pll; unsigned long r;
unsigned long r = 0; enum dss_clk_source src;
switch (dss_get_dispc_clk_source()) { src = dss_get_dispc_clk_source();
case OMAP_DSS_CLK_SRC_FCK:
if (src == DSS_CLK_SRC_FCK) {
r = dss_get_dispc_clk_rate(); r = dss_get_dispc_clk_rate();
break; } else {
case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: struct dss_pll *pll;
pll = dss_pll_find("dsi0"); unsigned clkout_idx;
if (!pll)
pll = dss_pll_find("video0");
r = pll->cinfo.clkout[0]; pll = dss_pll_find_by_src(src);
break; clkout_idx = dss_pll_get_clkout_idx_for_src(src);
case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
pll = dss_pll_find("dsi1");
if (!pll)
pll = dss_pll_find("video1");
r = pll->cinfo.clkout[0]; r = pll->cinfo.clkout[clkout_idx];
break;
default:
BUG();
return 0;
} }
return r; return r;
@ -3330,43 +3321,31 @@ static unsigned long dispc_fclk_rate(void)
static unsigned long dispc_mgr_lclk_rate(enum omap_channel channel) static unsigned long dispc_mgr_lclk_rate(enum omap_channel channel)
{ {
struct dss_pll *pll;
int lcd; int lcd;
unsigned long r; unsigned long r;
u32 l; enum dss_clk_source src;
if (dss_mgr_is_lcd(channel)) { /* for TV, LCLK rate is the FCLK rate */
l = dispc_read_reg(DISPC_DIVISORo(channel)); if (!dss_mgr_is_lcd(channel))
lcd = FLD_GET(l, 23, 16);
switch (dss_get_lcd_clk_source(channel)) {
case OMAP_DSS_CLK_SRC_FCK:
r = dss_get_dispc_clk_rate();
break;
case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
pll = dss_pll_find("dsi0");
if (!pll)
pll = dss_pll_find("video0");
r = pll->cinfo.clkout[0];
break;
case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
pll = dss_pll_find("dsi1");
if (!pll)
pll = dss_pll_find("video1");
r = pll->cinfo.clkout[0];
break;
default:
BUG();
return 0;
}
return r / lcd;
} else {
return dispc_fclk_rate(); return dispc_fclk_rate();
src = dss_get_lcd_clk_source(channel);
if (src == DSS_CLK_SRC_FCK) {
r = dss_get_dispc_clk_rate();
} else {
struct dss_pll *pll;
unsigned clkout_idx;
pll = dss_pll_find_by_src(src);
clkout_idx = dss_pll_get_clkout_idx_for_src(src);
r = pll->cinfo.clkout[clkout_idx];
} }
lcd = REG_GET(DISPC_DIVISORo(channel), 23, 16);
return r / lcd;
} }
static unsigned long dispc_mgr_pclk_rate(enum omap_channel channel) static unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
@ -3426,15 +3405,14 @@ static unsigned long dispc_plane_lclk_rate(enum omap_plane plane)
static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel) static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel)
{ {
int lcd, pcd; int lcd, pcd;
enum omap_dss_clk_source lcd_clk_src; enum dss_clk_source lcd_clk_src;
seq_printf(s, "- %s -\n", mgr_desc[channel].name); seq_printf(s, "- %s -\n", mgr_desc[channel].name);
lcd_clk_src = dss_get_lcd_clk_source(channel); lcd_clk_src = dss_get_lcd_clk_source(channel);
seq_printf(s, "%s clk source = %s (%s)\n", mgr_desc[channel].name, seq_printf(s, "%s clk source = %s\n", mgr_desc[channel].name,
dss_get_generic_clk_source_name(lcd_clk_src), dss_get_clk_source_name(lcd_clk_src));
dss_feat_get_clk_source_name(lcd_clk_src));
dispc_mgr_get_lcd_divisor(channel, &lcd, &pcd); dispc_mgr_get_lcd_divisor(channel, &lcd, &pcd);
@ -3448,16 +3426,15 @@ void dispc_dump_clocks(struct seq_file *s)
{ {
int lcd; int lcd;
u32 l; u32 l;
enum omap_dss_clk_source dispc_clk_src = dss_get_dispc_clk_source(); enum dss_clk_source dispc_clk_src = dss_get_dispc_clk_source();
if (dispc_runtime_get()) if (dispc_runtime_get())
return; return;
seq_printf(s, "- DISPC -\n"); seq_printf(s, "- DISPC -\n");
seq_printf(s, "dispc fclk source = %s (%s)\n", seq_printf(s, "dispc fclk source = %s\n",
dss_get_generic_clk_source_name(dispc_clk_src), dss_get_clk_source_name(dispc_clk_src));
dss_feat_get_clk_source_name(dispc_clk_src));
seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate()); seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate());

View File

@ -39,12 +39,11 @@
#include "dss.h" #include "dss.h"
#include "dss_features.h" #include "dss_features.h"
#define HSDIV_DISPC 0
struct dpi_data { struct dpi_data {
struct platform_device *pdev; struct platform_device *pdev;
struct regulator *vdds_dsi_reg; struct regulator *vdds_dsi_reg;
enum dss_clk_source clk_src;
struct dss_pll *pll; struct dss_pll *pll;
struct mutex lock; struct mutex lock;
@ -69,7 +68,7 @@ static struct dpi_data *dpi_get_data_from_pdev(struct platform_device *pdev)
return dev_get_drvdata(&pdev->dev); return dev_get_drvdata(&pdev->dev);
} }
static struct dss_pll *dpi_get_pll(enum omap_channel channel) static enum dss_clk_source dpi_get_clk_src(enum omap_channel channel)
{ {
/* /*
* XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL * XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL
@ -83,64 +82,51 @@ static struct dss_pll *dpi_get_pll(enum omap_channel channel)
case OMAPDSS_VER_OMAP3630: case OMAPDSS_VER_OMAP3630:
case OMAPDSS_VER_AM35xx: case OMAPDSS_VER_AM35xx:
case OMAPDSS_VER_AM43xx: case OMAPDSS_VER_AM43xx:
return NULL; return DSS_CLK_SRC_FCK;
case OMAPDSS_VER_OMAP4430_ES1: case OMAPDSS_VER_OMAP4430_ES1:
case OMAPDSS_VER_OMAP4430_ES2: case OMAPDSS_VER_OMAP4430_ES2:
case OMAPDSS_VER_OMAP4: case OMAPDSS_VER_OMAP4:
switch (channel) { switch (channel) {
case OMAP_DSS_CHANNEL_LCD: case OMAP_DSS_CHANNEL_LCD:
return dss_pll_find("dsi0"); return DSS_CLK_SRC_PLL1_1;
case OMAP_DSS_CHANNEL_LCD2: case OMAP_DSS_CHANNEL_LCD2:
return dss_pll_find("dsi1"); return DSS_CLK_SRC_PLL2_1;
default: default:
return NULL; return DSS_CLK_SRC_FCK;
} }
case OMAPDSS_VER_OMAP5: case OMAPDSS_VER_OMAP5:
switch (channel) { switch (channel) {
case OMAP_DSS_CHANNEL_LCD: case OMAP_DSS_CHANNEL_LCD:
return dss_pll_find("dsi0"); return DSS_CLK_SRC_PLL1_1;
case OMAP_DSS_CHANNEL_LCD3: case OMAP_DSS_CHANNEL_LCD3:
return dss_pll_find("dsi1"); return DSS_CLK_SRC_PLL2_1;
case OMAP_DSS_CHANNEL_LCD2:
default: default:
return NULL; return DSS_CLK_SRC_FCK;
} }
case OMAPDSS_VER_DRA7xx: case OMAPDSS_VER_DRA7xx:
switch (channel) { switch (channel) {
case OMAP_DSS_CHANNEL_LCD: case OMAP_DSS_CHANNEL_LCD:
return DSS_CLK_SRC_PLL1_1;
case OMAP_DSS_CHANNEL_LCD2: case OMAP_DSS_CHANNEL_LCD2:
return dss_pll_find("video0"); return DSS_CLK_SRC_PLL1_3;
case OMAP_DSS_CHANNEL_LCD3: case OMAP_DSS_CHANNEL_LCD3:
return dss_pll_find("video1"); return DSS_CLK_SRC_PLL2_1;
default: default:
return NULL; return DSS_CLK_SRC_FCK;
} }
default: default:
return NULL; return DSS_CLK_SRC_FCK;
}
}
static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
{
switch (channel) {
case OMAP_DSS_CHANNEL_LCD:
return OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC;
case OMAP_DSS_CHANNEL_LCD2:
return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
case OMAP_DSS_CHANNEL_LCD3:
return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
default:
/* this shouldn't happen */
WARN_ON(1);
return OMAP_DSS_CLK_SRC_FCK;
} }
} }
struct dpi_clk_calc_ctx { struct dpi_clk_calc_ctx {
struct dss_pll *pll; struct dss_pll *pll;
unsigned clkout_idx;
/* inputs */ /* inputs */
@ -148,7 +134,7 @@ struct dpi_clk_calc_ctx {
/* outputs */ /* outputs */
struct dss_pll_clock_info dsi_cinfo; struct dss_pll_clock_info pll_cinfo;
unsigned long fck; unsigned long fck;
struct dispc_clock_info dispc_cinfo; struct dispc_clock_info dispc_cinfo;
}; };
@ -193,8 +179,8 @@ static bool dpi_calc_hsdiv_cb(int m_dispc, unsigned long dispc,
if (m_dispc > 1 && m_dispc % 2 != 0 && ctx->pck_min >= 100000000) if (m_dispc > 1 && m_dispc % 2 != 0 && ctx->pck_min >= 100000000)
return false; return false;
ctx->dsi_cinfo.mX[HSDIV_DISPC] = m_dispc; ctx->pll_cinfo.mX[ctx->clkout_idx] = m_dispc;
ctx->dsi_cinfo.clkout[HSDIV_DISPC] = dispc; ctx->pll_cinfo.clkout[ctx->clkout_idx] = dispc;
return dispc_div_calc(dispc, ctx->pck_min, ctx->pck_max, return dispc_div_calc(dispc, ctx->pck_min, ctx->pck_max,
dpi_calc_dispc_cb, ctx); dpi_calc_dispc_cb, ctx);
@ -207,12 +193,12 @@ static bool dpi_calc_pll_cb(int n, int m, unsigned long fint,
{ {
struct dpi_clk_calc_ctx *ctx = data; struct dpi_clk_calc_ctx *ctx = data;
ctx->dsi_cinfo.n = n; ctx->pll_cinfo.n = n;
ctx->dsi_cinfo.m = m; ctx->pll_cinfo.m = m;
ctx->dsi_cinfo.fint = fint; ctx->pll_cinfo.fint = fint;
ctx->dsi_cinfo.clkdco = clkdco; ctx->pll_cinfo.clkdco = clkdco;
return dss_pll_hsdiv_calc(ctx->pll, clkdco, return dss_pll_hsdiv_calc_a(ctx->pll, clkdco,
ctx->pck_min, dss_feat_get_param_max(FEAT_PARAM_DSS_FCK), ctx->pck_min, dss_feat_get_param_max(FEAT_PARAM_DSS_FCK),
dpi_calc_hsdiv_cb, ctx); dpi_calc_hsdiv_cb, ctx);
} }
@ -227,25 +213,39 @@ static bool dpi_calc_dss_cb(unsigned long fck, void *data)
dpi_calc_dispc_cb, ctx); dpi_calc_dispc_cb, ctx);
} }
static bool dpi_dsi_clk_calc(struct dpi_data *dpi, unsigned long pck, static bool dpi_pll_clk_calc(struct dpi_data *dpi, unsigned long pck,
struct dpi_clk_calc_ctx *ctx) struct dpi_clk_calc_ctx *ctx)
{ {
unsigned long clkin; unsigned long clkin;
unsigned long pll_min, pll_max;
memset(ctx, 0, sizeof(*ctx)); memset(ctx, 0, sizeof(*ctx));
ctx->pll = dpi->pll; ctx->pll = dpi->pll;
ctx->pck_min = pck - 1000; ctx->clkout_idx = dss_pll_get_clkout_idx_for_src(dpi->clk_src);
ctx->pck_max = pck + 1000;
pll_min = 0; clkin = clk_get_rate(dpi->pll->clkin);
pll_max = 0;
clkin = clk_get_rate(ctx->pll->clkin); if (dpi->pll->hw->type == DSS_PLL_TYPE_A) {
unsigned long pll_min, pll_max;
return dss_pll_calc(ctx->pll, clkin, ctx->pck_min = pck - 1000;
pll_min, pll_max, ctx->pck_max = pck + 1000;
dpi_calc_pll_cb, ctx);
pll_min = 0;
pll_max = 0;
return dss_pll_calc_a(ctx->pll, clkin,
pll_min, pll_max,
dpi_calc_pll_cb, ctx);
} else { /* DSS_PLL_TYPE_B */
dss_pll_calc_b(dpi->pll, clkin, pck, &ctx->pll_cinfo);
ctx->dispc_cinfo.lck_div = 1;
ctx->dispc_cinfo.pck_div = 1;
ctx->dispc_cinfo.lck = ctx->pll_cinfo.clkout[0];
ctx->dispc_cinfo.pck = ctx->dispc_cinfo.lck;
return true;
}
} }
static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx) static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
@ -279,7 +279,7 @@ static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
static int dpi_set_dsi_clk(struct dpi_data *dpi, enum omap_channel channel, static int dpi_set_pll_clk(struct dpi_data *dpi, enum omap_channel channel,
unsigned long pck_req, unsigned long *fck, int *lck_div, unsigned long pck_req, unsigned long *fck, int *lck_div,
int *pck_div) int *pck_div)
{ {
@ -287,20 +287,19 @@ static int dpi_set_dsi_clk(struct dpi_data *dpi, enum omap_channel channel,
int r; int r;
bool ok; bool ok;
ok = dpi_dsi_clk_calc(dpi, pck_req, &ctx); ok = dpi_pll_clk_calc(dpi, pck_req, &ctx);
if (!ok) if (!ok)
return -EINVAL; return -EINVAL;
r = dss_pll_set_config(dpi->pll, &ctx.dsi_cinfo); r = dss_pll_set_config(dpi->pll, &ctx.pll_cinfo);
if (r) if (r)
return r; return r;
dss_select_lcd_clk_source(channel, dss_select_lcd_clk_source(channel, dpi->clk_src);
dpi_get_alt_clk_src(channel));
dpi->mgr_config.clock_info = ctx.dispc_cinfo; dpi->mgr_config.clock_info = ctx.dispc_cinfo;
*fck = ctx.dsi_cinfo.clkout[HSDIV_DISPC]; *fck = ctx.pll_cinfo.clkout[ctx.clkout_idx];
*lck_div = ctx.dispc_cinfo.lck_div; *lck_div = ctx.dispc_cinfo.lck_div;
*pck_div = ctx.dispc_cinfo.pck_div; *pck_div = ctx.dispc_cinfo.pck_div;
@ -342,7 +341,7 @@ static int dpi_set_mode(struct dpi_data *dpi)
int r = 0; int r = 0;
if (dpi->pll) if (dpi->pll)
r = dpi_set_dsi_clk(dpi, channel, t->pixelclock, &fck, r = dpi_set_pll_clk(dpi, channel, t->pixelclock, &fck,
&lck_div, &pck_div); &lck_div, &pck_div);
else else
r = dpi_set_dispc_clk(dpi, t->pixelclock, &fck, r = dpi_set_dispc_clk(dpi, t->pixelclock, &fck,
@ -419,7 +418,7 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
if (dpi->pll) { if (dpi->pll) {
r = dss_pll_enable(dpi->pll); r = dss_pll_enable(dpi->pll);
if (r) if (r)
goto err_dsi_pll_init; goto err_pll_init;
} }
r = dpi_set_mode(dpi); r = dpi_set_mode(dpi);
@ -442,7 +441,7 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
err_set_mode: err_set_mode:
if (dpi->pll) if (dpi->pll)
dss_pll_disable(dpi->pll); dss_pll_disable(dpi->pll);
err_dsi_pll_init: err_pll_init:
err_src_sel: err_src_sel:
dispc_runtime_put(); dispc_runtime_put();
err_get_dispc: err_get_dispc:
@ -465,7 +464,7 @@ static void dpi_display_disable(struct omap_dss_device *dssdev)
dss_mgr_disable(channel); dss_mgr_disable(channel);
if (dpi->pll) { if (dpi->pll) {
dss_select_lcd_clk_source(channel, OMAP_DSS_CLK_SRC_FCK); dss_select_lcd_clk_source(channel, DSS_CLK_SRC_FCK);
dss_pll_disable(dpi->pll); dss_pll_disable(dpi->pll);
} }
@ -524,11 +523,11 @@ static int dpi_check_timings(struct omap_dss_device *dssdev,
return -EINVAL; return -EINVAL;
if (dpi->pll) { if (dpi->pll) {
ok = dpi_dsi_clk_calc(dpi, timings->pixelclock, &ctx); ok = dpi_pll_clk_calc(dpi, timings->pixelclock, &ctx);
if (!ok) if (!ok)
return -EINVAL; return -EINVAL;
fck = ctx.dsi_cinfo.clkout[HSDIV_DISPC]; fck = ctx.pll_cinfo.clkout[ctx.clkout_idx];
} else { } else {
ok = dpi_dss_clk_calc(timings->pixelclock, &ctx); ok = dpi_dss_clk_calc(timings->pixelclock, &ctx);
if (!ok) if (!ok)
@ -558,7 +557,7 @@ static void dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
mutex_unlock(&dpi->lock); mutex_unlock(&dpi->lock);
} }
static int dpi_verify_dsi_pll(struct dss_pll *pll) static int dpi_verify_pll(struct dss_pll *pll)
{ {
int r; int r;
@ -602,16 +601,14 @@ static void dpi_init_pll(struct dpi_data *dpi)
if (dpi->pll) if (dpi->pll)
return; return;
pll = dpi_get_pll(dpi->output.dispc_channel); dpi->clk_src = dpi_get_clk_src(dpi->output.dispc_channel);
pll = dss_pll_find_by_src(dpi->clk_src);
if (!pll) if (!pll)
return; return;
/* On DRA7 we need to set a mux to use the PLL */ if (dpi_verify_pll(pll)) {
if (omapdss_get_version() == OMAPDSS_VER_DRA7xx) DSSWARN("PLL not operational\n");
dss_ctrl_pll_set_control_mux(pll->id, dpi->output.dispc_channel);
if (dpi_verify_dsi_pll(pll)) {
DSSWARN("DSI PLL not operational\n");
return; return;
} }

View File

@ -1262,7 +1262,7 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
unsigned long r; unsigned long r;
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
if (dss_get_dsi_clk_source(dsi->module_id) == OMAP_DSS_CLK_SRC_FCK) { if (dss_get_dsi_clk_source(dsi->module_id) == DSS_CLK_SRC_FCK) {
/* DSI FCLK source is DSS_CLK_FCK */ /* DSI FCLK source is DSS_CLK_FCK */
r = clk_get_rate(dsi->dss_clk); r = clk_get_rate(dsi->dss_clk);
} else { } else {
@ -1475,7 +1475,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
{ {
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
struct dss_pll_clock_info *cinfo = &dsi->pll.cinfo; struct dss_pll_clock_info *cinfo = &dsi->pll.cinfo;
enum omap_dss_clk_source dispc_clk_src, dsi_clk_src; enum dss_clk_source dispc_clk_src, dsi_clk_src;
int dsi_module = dsi->module_id; int dsi_module = dsi->module_id;
struct dss_pll *pll = &dsi->pll; struct dss_pll *pll = &dsi->pll;
@ -1495,28 +1495,27 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
cinfo->clkdco, cinfo->m); cinfo->clkdco, cinfo->m);
seq_printf(s, "DSI_PLL_HSDIV_DISPC (%s)\t%-16lum_dispc %u\t(%s)\n", seq_printf(s, "DSI_PLL_HSDIV_DISPC (%s)\t%-16lum_dispc %u\t(%s)\n",
dss_feat_get_clk_source_name(dsi_module == 0 ? dss_get_clk_source_name(dsi_module == 0 ?
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC : DSS_CLK_SRC_PLL1_1 :
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC), DSS_CLK_SRC_PLL2_1),
cinfo->clkout[HSDIV_DISPC], cinfo->clkout[HSDIV_DISPC],
cinfo->mX[HSDIV_DISPC], cinfo->mX[HSDIV_DISPC],
dispc_clk_src == OMAP_DSS_CLK_SRC_FCK ? dispc_clk_src == DSS_CLK_SRC_FCK ?
"off" : "on"); "off" : "on");
seq_printf(s, "DSI_PLL_HSDIV_DSI (%s)\t%-16lum_dsi %u\t(%s)\n", seq_printf(s, "DSI_PLL_HSDIV_DSI (%s)\t%-16lum_dsi %u\t(%s)\n",
dss_feat_get_clk_source_name(dsi_module == 0 ? dss_get_clk_source_name(dsi_module == 0 ?
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI : DSS_CLK_SRC_PLL1_2 :
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI), DSS_CLK_SRC_PLL2_2),
cinfo->clkout[HSDIV_DSI], cinfo->clkout[HSDIV_DSI],
cinfo->mX[HSDIV_DSI], cinfo->mX[HSDIV_DSI],
dsi_clk_src == OMAP_DSS_CLK_SRC_FCK ? dsi_clk_src == DSS_CLK_SRC_FCK ?
"off" : "on"); "off" : "on");
seq_printf(s, "- DSI%d -\n", dsi_module + 1); seq_printf(s, "- DSI%d -\n", dsi_module + 1);
seq_printf(s, "dsi fclk source = %s (%s)\n", seq_printf(s, "dsi fclk source = %s\n",
dss_get_generic_clk_source_name(dsi_clk_src), dss_get_clk_source_name(dsi_clk_src));
dss_feat_get_clk_source_name(dsi_clk_src));
seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate(dsidev)); seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate(dsidev));
@ -4102,8 +4101,8 @@ static int dsi_display_init_dispc(struct platform_device *dsidev,
int r; int r;
dss_select_lcd_clk_source(channel, dsi->module_id == 0 ? dss_select_lcd_clk_source(channel, dsi->module_id == 0 ?
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC : DSS_CLK_SRC_PLL1_1 :
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC); DSS_CLK_SRC_PLL2_1);
if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) { if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
r = dss_mgr_register_framedone_handler(channel, r = dss_mgr_register_framedone_handler(channel,
@ -4150,7 +4149,7 @@ static int dsi_display_init_dispc(struct platform_device *dsidev,
dss_mgr_unregister_framedone_handler(channel, dss_mgr_unregister_framedone_handler(channel,
dsi_framedone_irq_callback, dsidev); dsi_framedone_irq_callback, dsidev);
err: err:
dss_select_lcd_clk_source(channel, OMAP_DSS_CLK_SRC_FCK); dss_select_lcd_clk_source(channel, DSS_CLK_SRC_FCK);
return r; return r;
} }
@ -4163,7 +4162,7 @@ static void dsi_display_uninit_dispc(struct platform_device *dsidev,
dss_mgr_unregister_framedone_handler(channel, dss_mgr_unregister_framedone_handler(channel,
dsi_framedone_irq_callback, dsidev); dsi_framedone_irq_callback, dsidev);
dss_select_lcd_clk_source(channel, OMAP_DSS_CLK_SRC_FCK); dss_select_lcd_clk_source(channel, DSS_CLK_SRC_FCK);
} }
static int dsi_configure_dsi_clocks(struct platform_device *dsidev) static int dsi_configure_dsi_clocks(struct platform_device *dsidev)
@ -4197,8 +4196,8 @@ static int dsi_display_init_dsi(struct platform_device *dsidev)
goto err1; goto err1;
dss_select_dsi_clk_source(dsi->module_id, dsi->module_id == 0 ? dss_select_dsi_clk_source(dsi->module_id, dsi->module_id == 0 ?
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI : DSS_CLK_SRC_PLL1_2 :
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI); DSS_CLK_SRC_PLL2_2);
DSSDBG("PLL OK\n"); DSSDBG("PLL OK\n");
@ -4230,7 +4229,7 @@ static int dsi_display_init_dsi(struct platform_device *dsidev)
err3: err3:
dsi_cio_uninit(dsidev); dsi_cio_uninit(dsidev);
err2: err2:
dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); dss_select_dsi_clk_source(dsi->module_id, DSS_CLK_SRC_FCK);
err1: err1:
dss_pll_disable(&dsi->pll); dss_pll_disable(&dsi->pll);
err0: err0:
@ -4252,7 +4251,7 @@ static void dsi_display_uninit_dsi(struct platform_device *dsidev,
dsi_vc_enable(dsidev, 2, 0); dsi_vc_enable(dsidev, 2, 0);
dsi_vc_enable(dsidev, 3, 0); dsi_vc_enable(dsidev, 3, 0);
dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); dss_select_dsi_clk_source(dsi->module_id, DSS_CLK_SRC_FCK);
dsi_cio_uninit(dsidev); dsi_cio_uninit(dsidev);
dsi_pll_uninit(dsidev, disconnect_lanes); dsi_pll_uninit(dsidev, disconnect_lanes);
} }
@ -4453,7 +4452,7 @@ static bool dsi_cm_calc_pll_cb(int n, int m, unsigned long fint,
ctx->dsi_cinfo.fint = fint; ctx->dsi_cinfo.fint = fint;
ctx->dsi_cinfo.clkdco = clkdco; ctx->dsi_cinfo.clkdco = clkdco;
return dss_pll_hsdiv_calc(ctx->pll, clkdco, ctx->req_pck_min, return dss_pll_hsdiv_calc_a(ctx->pll, clkdco, ctx->req_pck_min,
dss_feat_get_param_max(FEAT_PARAM_DSS_FCK), dss_feat_get_param_max(FEAT_PARAM_DSS_FCK),
dsi_cm_calc_hsdiv_cb, ctx); dsi_cm_calc_hsdiv_cb, ctx);
} }
@ -4492,7 +4491,7 @@ static bool dsi_cm_calc(struct dsi_data *dsi,
pll_min = max(cfg->hs_clk_min * 4, txbyteclk * 4 * 4); pll_min = max(cfg->hs_clk_min * 4, txbyteclk * 4 * 4);
pll_max = cfg->hs_clk_max * 4; pll_max = cfg->hs_clk_max * 4;
return dss_pll_calc(ctx->pll, clkin, return dss_pll_calc_a(ctx->pll, clkin,
pll_min, pll_max, pll_min, pll_max,
dsi_cm_calc_pll_cb, ctx); dsi_cm_calc_pll_cb, ctx);
} }
@ -4751,7 +4750,7 @@ static bool dsi_vm_calc_pll_cb(int n, int m, unsigned long fint,
ctx->dsi_cinfo.fint = fint; ctx->dsi_cinfo.fint = fint;
ctx->dsi_cinfo.clkdco = clkdco; ctx->dsi_cinfo.clkdco = clkdco;
return dss_pll_hsdiv_calc(ctx->pll, clkdco, ctx->req_pck_min, return dss_pll_hsdiv_calc_a(ctx->pll, clkdco, ctx->req_pck_min,
dss_feat_get_param_max(FEAT_PARAM_DSS_FCK), dss_feat_get_param_max(FEAT_PARAM_DSS_FCK),
dsi_vm_calc_hsdiv_cb, ctx); dsi_vm_calc_hsdiv_cb, ctx);
} }
@ -4793,7 +4792,7 @@ static bool dsi_vm_calc(struct dsi_data *dsi,
pll_max = byteclk_max * 4 * 4; pll_max = byteclk_max * 4 * 4;
} }
return dss_pll_calc(ctx->pll, clkin, return dss_pll_calc_a(ctx->pll, clkin,
pll_min, pll_max, pll_min, pll_max,
dsi_vm_calc_pll_cb, ctx); dsi_vm_calc_pll_cb, ctx);
} }
@ -5139,6 +5138,8 @@ static const struct dss_pll_ops dsi_pll_ops = {
}; };
static const struct dss_pll_hw dss_omap3_dsi_pll_hw = { static const struct dss_pll_hw dss_omap3_dsi_pll_hw = {
.type = DSS_PLL_TYPE_A,
.n_max = (1 << 7) - 1, .n_max = (1 << 7) - 1,
.m_max = (1 << 11) - 1, .m_max = (1 << 11) - 1,
.mX_max = (1 << 4) - 1, .mX_max = (1 << 4) - 1,
@ -5164,6 +5165,8 @@ static const struct dss_pll_hw dss_omap3_dsi_pll_hw = {
}; };
static const struct dss_pll_hw dss_omap4_dsi_pll_hw = { static const struct dss_pll_hw dss_omap4_dsi_pll_hw = {
.type = DSS_PLL_TYPE_A,
.n_max = (1 << 8) - 1, .n_max = (1 << 8) - 1,
.m_max = (1 << 12) - 1, .m_max = (1 << 12) - 1,
.mX_max = (1 << 5) - 1, .mX_max = (1 << 5) - 1,
@ -5189,6 +5192,8 @@ static const struct dss_pll_hw dss_omap4_dsi_pll_hw = {
}; };
static const struct dss_pll_hw dss_omap5_dsi_pll_hw = { static const struct dss_pll_hw dss_omap5_dsi_pll_hw = {
.type = DSS_PLL_TYPE_A,
.n_max = (1 << 8) - 1, .n_max = (1 << 8) - 1,
.m_max = (1 << 12) - 1, .m_max = (1 << 12) - 1,
.mX_max = (1 << 5) - 1, .mX_max = (1 << 5) - 1,

View File

@ -76,6 +76,8 @@ struct dss_features {
const enum omap_display_type *ports; const enum omap_display_type *ports;
int num_ports; int num_ports;
int (*dpi_select_source)(int port, enum omap_channel channel); int (*dpi_select_source)(int port, enum omap_channel channel);
int (*select_lcd_source)(enum omap_channel channel,
enum dss_clk_source clk_src);
}; };
static struct { static struct {
@ -92,9 +94,9 @@ static struct {
unsigned long cache_prate; unsigned long cache_prate;
struct dispc_clock_info cache_dispc_cinfo; struct dispc_clock_info cache_dispc_cinfo;
enum omap_dss_clk_source dsi_clk_source[MAX_NUM_DSI]; enum dss_clk_source dsi_clk_source[MAX_NUM_DSI];
enum omap_dss_clk_source dispc_clk_source; enum dss_clk_source dispc_clk_source;
enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS]; enum dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
bool ctx_valid; bool ctx_valid;
u32 ctx[DSS_SZ_REGS / sizeof(u32)]; u32 ctx[DSS_SZ_REGS / sizeof(u32)];
@ -106,11 +108,14 @@ static struct {
} dss; } dss;
static const char * const dss_generic_clk_source_names[] = { static const char * const dss_generic_clk_source_names[] = {
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC", [DSS_CLK_SRC_FCK] = "FCK",
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI", [DSS_CLK_SRC_PLL1_1] = "PLL1:1",
[OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK", [DSS_CLK_SRC_PLL1_2] = "PLL1:2",
[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "DSI_PLL2_HSDIV_DISPC", [DSS_CLK_SRC_PLL1_3] = "PLL1:3",
[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DSI_PLL2_HSDIV_DSI", [DSS_CLK_SRC_PLL2_1] = "PLL2:1",
[DSS_CLK_SRC_PLL2_2] = "PLL2:2",
[DSS_CLK_SRC_PLL2_3] = "PLL2:3",
[DSS_CLK_SRC_HDMI_PLL] = "HDMI PLL",
}; };
static bool dss_initialized; static bool dss_initialized;
@ -203,68 +208,70 @@ void dss_ctrl_pll_enable(enum dss_pll_id pll_id, bool enable)
1 << shift, val << shift); 1 << shift, val << shift);
} }
void dss_ctrl_pll_set_control_mux(enum dss_pll_id pll_id, static int dss_ctrl_pll_set_control_mux(enum dss_clk_source clk_src,
enum omap_channel channel) enum omap_channel channel)
{ {
unsigned shift, val; unsigned shift, val;
if (!dss.syscon_pll_ctrl) if (!dss.syscon_pll_ctrl)
return; return -EINVAL;
switch (channel) { switch (channel) {
case OMAP_DSS_CHANNEL_LCD: case OMAP_DSS_CHANNEL_LCD:
shift = 3; shift = 3;
switch (pll_id) { switch (clk_src) {
case DSS_PLL_VIDEO1: case DSS_CLK_SRC_PLL1_1:
val = 0; break; val = 0; break;
case DSS_PLL_HDMI: case DSS_CLK_SRC_HDMI_PLL:
val = 1; break; val = 1; break;
default: default:
DSSERR("error in PLL mux config for LCD\n"); DSSERR("error in PLL mux config for LCD\n");
return; return -EINVAL;
} }
break; break;
case OMAP_DSS_CHANNEL_LCD2: case OMAP_DSS_CHANNEL_LCD2:
shift = 5; shift = 5;
switch (pll_id) { switch (clk_src) {
case DSS_PLL_VIDEO1: case DSS_CLK_SRC_PLL1_3:
val = 0; break; val = 0; break;
case DSS_PLL_VIDEO2: case DSS_CLK_SRC_PLL2_3:
val = 1; break; val = 1; break;
case DSS_PLL_HDMI: case DSS_CLK_SRC_HDMI_PLL:
val = 2; break; val = 2; break;
default: default:
DSSERR("error in PLL mux config for LCD2\n"); DSSERR("error in PLL mux config for LCD2\n");
return; return -EINVAL;
} }
break; break;
case OMAP_DSS_CHANNEL_LCD3: case OMAP_DSS_CHANNEL_LCD3:
shift = 7; shift = 7;
switch (pll_id) { switch (clk_src) {
case DSS_PLL_VIDEO1: case DSS_CLK_SRC_PLL2_1:
val = 1; break;
case DSS_PLL_VIDEO2:
val = 0; break; val = 0; break;
case DSS_PLL_HDMI: case DSS_CLK_SRC_PLL1_3:
val = 1; break;
case DSS_CLK_SRC_HDMI_PLL:
val = 2; break; val = 2; break;
default: default:
DSSERR("error in PLL mux config for LCD3\n"); DSSERR("error in PLL mux config for LCD3\n");
return; return -EINVAL;
} }
break; break;
default: default:
DSSERR("error in PLL mux config\n"); DSSERR("error in PLL mux config\n");
return; return -EINVAL;
} }
regmap_update_bits(dss.syscon_pll_ctrl, dss.syscon_pll_ctrl_offset, regmap_update_bits(dss.syscon_pll_ctrl, dss.syscon_pll_ctrl_offset,
0x3 << shift, val << shift); 0x3 << shift, val << shift);
return 0;
} }
void dss_sdi_init(int datapairs) void dss_sdi_init(int datapairs)
@ -354,14 +361,14 @@ void dss_sdi_disable(void)
REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */ REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
} }
const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src) const char *dss_get_clk_source_name(enum dss_clk_source clk_src)
{ {
return dss_generic_clk_source_names[clk_src]; return dss_generic_clk_source_names[clk_src];
} }
void dss_dump_clocks(struct seq_file *s) void dss_dump_clocks(struct seq_file *s)
{ {
const char *fclk_name, *fclk_real_name; const char *fclk_name;
unsigned long fclk_rate; unsigned long fclk_rate;
if (dss_runtime_get()) if (dss_runtime_get())
@ -369,12 +376,11 @@ void dss_dump_clocks(struct seq_file *s)
seq_printf(s, "- DSS -\n"); seq_printf(s, "- DSS -\n");
fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK); fclk_name = dss_get_clk_source_name(DSS_CLK_SRC_FCK);
fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
fclk_rate = clk_get_rate(dss.dss_clk); fclk_rate = clk_get_rate(dss.dss_clk);
seq_printf(s, "%s (%s) = %lu\n", seq_printf(s, "%s = %lu\n",
fclk_name, fclk_real_name, fclk_name,
fclk_rate); fclk_rate);
dss_runtime_put(); dss_runtime_put();
@ -403,19 +409,42 @@ static void dss_dump_regs(struct seq_file *s)
#undef DUMPREG #undef DUMPREG
} }
static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src) static int dss_get_channel_index(enum omap_channel channel)
{
switch (channel) {
case OMAP_DSS_CHANNEL_LCD:
return 0;
case OMAP_DSS_CHANNEL_LCD2:
return 1;
case OMAP_DSS_CHANNEL_LCD3:
return 2;
default:
WARN_ON(1);
return 0;
}
}
static void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
{ {
int b; int b;
u8 start, end; u8 start, end;
/*
* We always use PRCM clock as the DISPC func clock, except on DSS3,
* where we don't have separate DISPC and LCD clock sources.
*/
if (WARN_ON(dss_has_feature(FEAT_LCD_CLK_SRC) &&
clk_src != DSS_CLK_SRC_FCK))
return;
switch (clk_src) { switch (clk_src) {
case OMAP_DSS_CLK_SRC_FCK: case DSS_CLK_SRC_FCK:
b = 0; b = 0;
break; break;
case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: case DSS_CLK_SRC_PLL1_1:
b = 1; b = 1;
break; break;
case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: case DSS_CLK_SRC_PLL2_1:
b = 2; b = 2;
break; break;
default: default:
@ -431,19 +460,19 @@ static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
} }
void dss_select_dsi_clk_source(int dsi_module, void dss_select_dsi_clk_source(int dsi_module,
enum omap_dss_clk_source clk_src) enum dss_clk_source clk_src)
{ {
int b, pos; int b, pos;
switch (clk_src) { switch (clk_src) {
case OMAP_DSS_CLK_SRC_FCK: case DSS_CLK_SRC_FCK:
b = 0; b = 0;
break; break;
case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI: case DSS_CLK_SRC_PLL1_2:
BUG_ON(dsi_module != 0); BUG_ON(dsi_module != 0);
b = 1; b = 1;
break; break;
case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI: case DSS_CLK_SRC_PLL2_2:
BUG_ON(dsi_module != 1); BUG_ON(dsi_module != 1);
b = 1; b = 1;
break; break;
@ -458,59 +487,125 @@ void dss_select_dsi_clk_source(int dsi_module,
dss.dsi_clk_source[dsi_module] = clk_src; dss.dsi_clk_source[dsi_module] = clk_src;
} }
void dss_select_lcd_clk_source(enum omap_channel channel, static int dss_lcd_clk_mux_dra7(enum omap_channel channel,
enum omap_dss_clk_source clk_src) enum dss_clk_source clk_src)
{ {
int b, ix, pos; const u8 ctrl_bits[] = {
[OMAP_DSS_CHANNEL_LCD] = 0,
[OMAP_DSS_CHANNEL_LCD2] = 12,
[OMAP_DSS_CHANNEL_LCD3] = 19,
};
u8 ctrl_bit = ctrl_bits[channel];
int r;
if (clk_src == DSS_CLK_SRC_FCK) {
/* LCDx_CLK_SWITCH */
REG_FLD_MOD(DSS_CONTROL, 0, ctrl_bit, ctrl_bit);
return -EINVAL;
}
r = dss_ctrl_pll_set_control_mux(clk_src, channel);
if (r)
return r;
REG_FLD_MOD(DSS_CONTROL, 1, ctrl_bit, ctrl_bit);
return 0;
}
static int dss_lcd_clk_mux_omap5(enum omap_channel channel,
enum dss_clk_source clk_src)
{
const u8 ctrl_bits[] = {
[OMAP_DSS_CHANNEL_LCD] = 0,
[OMAP_DSS_CHANNEL_LCD2] = 12,
[OMAP_DSS_CHANNEL_LCD3] = 19,
};
const enum dss_clk_source allowed_plls[] = {
[OMAP_DSS_CHANNEL_LCD] = DSS_CLK_SRC_PLL1_1,
[OMAP_DSS_CHANNEL_LCD2] = DSS_CLK_SRC_FCK,
[OMAP_DSS_CHANNEL_LCD3] = DSS_CLK_SRC_PLL2_1,
};
u8 ctrl_bit = ctrl_bits[channel];
if (clk_src == DSS_CLK_SRC_FCK) {
/* LCDx_CLK_SWITCH */
REG_FLD_MOD(DSS_CONTROL, 0, ctrl_bit, ctrl_bit);
return -EINVAL;
}
if (WARN_ON(allowed_plls[channel] != clk_src))
return -EINVAL;
REG_FLD_MOD(DSS_CONTROL, 1, ctrl_bit, ctrl_bit);
return 0;
}
static int dss_lcd_clk_mux_omap4(enum omap_channel channel,
enum dss_clk_source clk_src)
{
const u8 ctrl_bits[] = {
[OMAP_DSS_CHANNEL_LCD] = 0,
[OMAP_DSS_CHANNEL_LCD2] = 12,
};
const enum dss_clk_source allowed_plls[] = {
[OMAP_DSS_CHANNEL_LCD] = DSS_CLK_SRC_PLL1_1,
[OMAP_DSS_CHANNEL_LCD2] = DSS_CLK_SRC_PLL2_1,
};
u8 ctrl_bit = ctrl_bits[channel];
if (clk_src == DSS_CLK_SRC_FCK) {
/* LCDx_CLK_SWITCH */
REG_FLD_MOD(DSS_CONTROL, 0, ctrl_bit, ctrl_bit);
return 0;
}
if (WARN_ON(allowed_plls[channel] != clk_src))
return -EINVAL;
REG_FLD_MOD(DSS_CONTROL, 1, ctrl_bit, ctrl_bit);
return 0;
}
void dss_select_lcd_clk_source(enum omap_channel channel,
enum dss_clk_source clk_src)
{
int idx = dss_get_channel_index(channel);
int r;
if (!dss_has_feature(FEAT_LCD_CLK_SRC)) { if (!dss_has_feature(FEAT_LCD_CLK_SRC)) {
dss_select_dispc_clk_source(clk_src); dss_select_dispc_clk_source(clk_src);
dss.lcd_clk_source[idx] = clk_src;
return; return;
} }
switch (clk_src) { r = dss.feat->select_lcd_source(channel, clk_src);
case OMAP_DSS_CLK_SRC_FCK: if (r)
b = 0;
break;
case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
BUG_ON(channel != OMAP_DSS_CHANNEL_LCD);
b = 1;
break;
case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2 &&
channel != OMAP_DSS_CHANNEL_LCD3);
b = 1;
break;
default:
BUG();
return; return;
}
pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 : dss.lcd_clk_source[idx] = clk_src;
(channel == OMAP_DSS_CHANNEL_LCD2 ? 12 : 19);
REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* LCDx_CLK_SWITCH */
ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
(channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2);
dss.lcd_clk_source[ix] = clk_src;
} }
enum omap_dss_clk_source dss_get_dispc_clk_source(void) enum dss_clk_source dss_get_dispc_clk_source(void)
{ {
return dss.dispc_clk_source; return dss.dispc_clk_source;
} }
enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module) enum dss_clk_source dss_get_dsi_clk_source(int dsi_module)
{ {
return dss.dsi_clk_source[dsi_module]; return dss.dsi_clk_source[dsi_module];
} }
enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel) enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
{ {
if (dss_has_feature(FEAT_LCD_CLK_SRC)) { if (dss_has_feature(FEAT_LCD_CLK_SRC)) {
int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : int idx = dss_get_channel_index(channel);
(channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2); return dss.lcd_clk_source[idx];
return dss.lcd_clk_source[ix];
} else { } else {
/* LCD_CLK source is the same as DISPC_FCLK source for /* LCD_CLK source is the same as DISPC_FCLK source for
* OMAP2 and OMAP3 */ * OMAP2 and OMAP3 */
@ -859,6 +954,7 @@ static const struct dss_features omap44xx_dss_feats = {
.dpi_select_source = &dss_dpi_select_source_omap4, .dpi_select_source = &dss_dpi_select_source_omap4,
.ports = omap2plus_ports, .ports = omap2plus_ports,
.num_ports = ARRAY_SIZE(omap2plus_ports), .num_ports = ARRAY_SIZE(omap2plus_ports),
.select_lcd_source = &dss_lcd_clk_mux_omap4,
}; };
static const struct dss_features omap54xx_dss_feats = { static const struct dss_features omap54xx_dss_feats = {
@ -868,6 +964,7 @@ static const struct dss_features omap54xx_dss_feats = {
.dpi_select_source = &dss_dpi_select_source_omap5, .dpi_select_source = &dss_dpi_select_source_omap5,
.ports = omap2plus_ports, .ports = omap2plus_ports,
.num_ports = ARRAY_SIZE(omap2plus_ports), .num_ports = ARRAY_SIZE(omap2plus_ports),
.select_lcd_source = &dss_lcd_clk_mux_omap5,
}; };
static const struct dss_features am43xx_dss_feats = { static const struct dss_features am43xx_dss_feats = {
@ -886,6 +983,7 @@ static const struct dss_features dra7xx_dss_feats = {
.dpi_select_source = &dss_dpi_select_source_dra7xx, .dpi_select_source = &dss_dpi_select_source_dra7xx,
.ports = dra7xx_ports, .ports = dra7xx_ports,
.num_ports = ARRAY_SIZE(dra7xx_ports), .num_ports = ARRAY_SIZE(dra7xx_ports),
.select_lcd_source = &dss_lcd_clk_mux_dra7,
}; };
static int dss_init_features(struct platform_device *pdev) static int dss_init_features(struct platform_device *pdev)
@ -1143,18 +1241,18 @@ static int dss_bind(struct device *dev)
/* Select DPLL */ /* Select DPLL */
REG_FLD_MOD(DSS_CONTROL, 0, 0, 0); REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); dss_select_dispc_clk_source(DSS_CLK_SRC_FCK);
#ifdef CONFIG_OMAP2_DSS_VENC #ifdef CONFIG_OMAP2_DSS_VENC
REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */ REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */
#endif #endif
dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; dss.dsi_clk_source[0] = DSS_CLK_SRC_FCK;
dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; dss.dsi_clk_source[1] = DSS_CLK_SRC_FCK;
dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK; dss.dispc_clk_source = DSS_CLK_SRC_FCK;
dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; dss.lcd_clk_source[0] = DSS_CLK_SRC_FCK;
dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; dss.lcd_clk_source[1] = DSS_CLK_SRC_FCK;
rev = dss_read_reg(DSS_REVISION); rev = dss_read_reg(DSS_REVISION);
printk(KERN_INFO "OMAP DSS rev %d.%d\n", printk(KERN_INFO "OMAP DSS rev %d.%d\n",

View File

@ -102,6 +102,20 @@ enum dss_writeback_channel {
DSS_WB_LCD3_MGR = 7, DSS_WB_LCD3_MGR = 7,
}; };
enum dss_clk_source {
DSS_CLK_SRC_FCK = 0,
DSS_CLK_SRC_PLL1_1,
DSS_CLK_SRC_PLL1_2,
DSS_CLK_SRC_PLL1_3,
DSS_CLK_SRC_PLL2_1,
DSS_CLK_SRC_PLL2_2,
DSS_CLK_SRC_PLL2_3,
DSS_CLK_SRC_HDMI_PLL,
};
enum dss_pll_id { enum dss_pll_id {
DSS_PLL_DSI1, DSS_PLL_DSI1,
DSS_PLL_DSI2, DSS_PLL_DSI2,
@ -114,6 +128,11 @@ struct dss_pll;
#define DSS_PLL_MAX_HSDIVS 4 #define DSS_PLL_MAX_HSDIVS 4
enum dss_pll_type {
DSS_PLL_TYPE_A,
DSS_PLL_TYPE_B,
};
/* /*
* Type-A PLLs: clkout[]/mX[] refer to hsdiv outputs m4, m5, m6, m7. * Type-A PLLs: clkout[]/mX[] refer to hsdiv outputs m4, m5, m6, m7.
* Type-B PLLs: clkout[0] refers to m2. * Type-B PLLs: clkout[0] refers to m2.
@ -140,6 +159,8 @@ struct dss_pll_ops {
}; };
struct dss_pll_hw { struct dss_pll_hw {
enum dss_pll_type type;
unsigned n_max; unsigned n_max;
unsigned m_min; unsigned m_min;
unsigned m_max; unsigned m_max;
@ -227,7 +248,7 @@ unsigned long dss_get_dispc_clk_rate(void);
int dss_dpi_select_source(int port, enum omap_channel channel); int dss_dpi_select_source(int port, enum omap_channel channel);
void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void); enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); const char *dss_get_clk_source_name(enum dss_clk_source clk_src);
void dss_dump_clocks(struct seq_file *s); void dss_dump_clocks(struct seq_file *s);
/* DSS VIDEO PLL */ /* DSS VIDEO PLL */
@ -244,20 +265,18 @@ void dss_debug_dump_clocks(struct seq_file *s);
#endif #endif
void dss_ctrl_pll_enable(enum dss_pll_id pll_id, bool enable); void dss_ctrl_pll_enable(enum dss_pll_id pll_id, bool enable);
void dss_ctrl_pll_set_control_mux(enum dss_pll_id pll_id,
enum omap_channel channel);
void dss_sdi_init(int datapairs); void dss_sdi_init(int datapairs);
int dss_sdi_enable(void); int dss_sdi_enable(void);
void dss_sdi_disable(void); void dss_sdi_disable(void);
void dss_select_dsi_clk_source(int dsi_module, void dss_select_dsi_clk_source(int dsi_module,
enum omap_dss_clk_source clk_src); enum dss_clk_source clk_src);
void dss_select_lcd_clk_source(enum omap_channel channel, void dss_select_lcd_clk_source(enum omap_channel channel,
enum omap_dss_clk_source clk_src); enum dss_clk_source clk_src);
enum omap_dss_clk_source dss_get_dispc_clk_source(void); enum dss_clk_source dss_get_dispc_clk_source(void);
enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module); enum dss_clk_source dss_get_dsi_clk_source(int dsi_module);
enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel); enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel);
void dss_set_venc_output(enum omap_dss_venc_type type); void dss_set_venc_output(enum omap_dss_venc_type type);
void dss_set_dac_pwrdn_bgz(bool enable); void dss_set_dac_pwrdn_bgz(bool enable);
@ -409,17 +428,23 @@ typedef bool (*dss_hsdiv_calc_func)(int m_dispc, unsigned long dispc,
int dss_pll_register(struct dss_pll *pll); int dss_pll_register(struct dss_pll *pll);
void dss_pll_unregister(struct dss_pll *pll); void dss_pll_unregister(struct dss_pll *pll);
struct dss_pll *dss_pll_find(const char *name); struct dss_pll *dss_pll_find(const char *name);
struct dss_pll *dss_pll_find_by_src(enum dss_clk_source src);
unsigned dss_pll_get_clkout_idx_for_src(enum dss_clk_source src);
int dss_pll_enable(struct dss_pll *pll); int dss_pll_enable(struct dss_pll *pll);
void dss_pll_disable(struct dss_pll *pll); void dss_pll_disable(struct dss_pll *pll);
int dss_pll_set_config(struct dss_pll *pll, int dss_pll_set_config(struct dss_pll *pll,
const struct dss_pll_clock_info *cinfo); const struct dss_pll_clock_info *cinfo);
bool dss_pll_hsdiv_calc(const struct dss_pll *pll, unsigned long clkdco, bool dss_pll_hsdiv_calc_a(const struct dss_pll *pll, unsigned long clkdco,
unsigned long out_min, unsigned long out_max, unsigned long out_min, unsigned long out_max,
dss_hsdiv_calc_func func, void *data); dss_hsdiv_calc_func func, void *data);
bool dss_pll_calc(const struct dss_pll *pll, unsigned long clkin, bool dss_pll_calc_a(const struct dss_pll *pll, unsigned long clkin,
unsigned long pll_min, unsigned long pll_max, unsigned long pll_min, unsigned long pll_max,
dss_pll_calc_func func, void *data); dss_pll_calc_func func, void *data);
bool dss_pll_calc_b(const struct dss_pll *pll, unsigned long clkin,
unsigned long target_clkout, struct dss_pll_clock_info *cinfo);
int dss_pll_write_config_type_a(struct dss_pll *pll, int dss_pll_write_config_type_a(struct dss_pll *pll,
const struct dss_pll_clock_info *cinfo); const struct dss_pll_clock_info *cinfo);
int dss_pll_write_config_type_b(struct dss_pll *pll, int dss_pll_write_config_type_b(struct dss_pll *pll,

View File

@ -50,7 +50,6 @@ struct omap_dss_features {
const enum omap_dss_output_id *supported_outputs; const enum omap_dss_output_id *supported_outputs;
const enum omap_color_mode *supported_color_modes; const enum omap_color_mode *supported_color_modes;
const enum omap_overlay_caps *overlay_caps; const enum omap_overlay_caps *overlay_caps;
const char * const *clksrc_names;
const struct dss_param_range *dss_params; const struct dss_param_range *dss_params;
const enum omap_dss_rotation_type supported_rotation_types; const enum omap_dss_rotation_type supported_rotation_types;
@ -389,34 +388,6 @@ static const enum omap_overlay_caps omap4_dss_overlay_caps[] = {
OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION, OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
}; };
static const char * const omap2_dss_clk_source_names[] = {
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "N/A",
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "N/A",
[OMAP_DSS_CLK_SRC_FCK] = "DSS_FCLK1",
};
static const char * const omap3_dss_clk_source_names[] = {
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI1_PLL_FCLK",
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI2_PLL_FCLK",
[OMAP_DSS_CLK_SRC_FCK] = "DSS1_ALWON_FCLK",
};
static const char * const omap4_dss_clk_source_names[] = {
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "PLL1_CLK1",
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "PLL1_CLK2",
[OMAP_DSS_CLK_SRC_FCK] = "DSS_FCLK",
[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "PLL2_CLK1",
[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "PLL2_CLK2",
};
static const char * const omap5_dss_clk_source_names[] = {
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DPLL_DSI1_A_CLK1",
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DPLL_DSI1_A_CLK2",
[OMAP_DSS_CLK_SRC_FCK] = "DSS_CLK",
[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "DPLL_DSI1_C_CLK1",
[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DPLL_DSI1_C_CLK2",
};
static const struct dss_param_range omap2_dss_param_range[] = { static const struct dss_param_range omap2_dss_param_range[] = {
[FEAT_PARAM_DSS_FCK] = { 0, 133000000 }, [FEAT_PARAM_DSS_FCK] = { 0, 133000000 },
[FEAT_PARAM_DSS_PCD] = { 2, 255 }, [FEAT_PARAM_DSS_PCD] = { 2, 255 },
@ -631,7 +602,6 @@ static const struct omap_dss_features omap2_dss_features = {
.supported_outputs = omap2_dss_supported_outputs, .supported_outputs = omap2_dss_supported_outputs,
.supported_color_modes = omap2_dss_supported_color_modes, .supported_color_modes = omap2_dss_supported_color_modes,
.overlay_caps = omap2_dss_overlay_caps, .overlay_caps = omap2_dss_overlay_caps,
.clksrc_names = omap2_dss_clk_source_names,
.dss_params = omap2_dss_param_range, .dss_params = omap2_dss_param_range,
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB, .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
.buffer_size_unit = 1, .buffer_size_unit = 1,
@ -652,7 +622,6 @@ static const struct omap_dss_features omap3430_dss_features = {
.supported_outputs = omap3430_dss_supported_outputs, .supported_outputs = omap3430_dss_supported_outputs,
.supported_color_modes = omap3_dss_supported_color_modes, .supported_color_modes = omap3_dss_supported_color_modes,
.overlay_caps = omap3430_dss_overlay_caps, .overlay_caps = omap3430_dss_overlay_caps,
.clksrc_names = omap3_dss_clk_source_names,
.dss_params = omap3_dss_param_range, .dss_params = omap3_dss_param_range,
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB, .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
.buffer_size_unit = 1, .buffer_size_unit = 1,
@ -676,7 +645,6 @@ static const struct omap_dss_features am35xx_dss_features = {
.supported_outputs = omap3430_dss_supported_outputs, .supported_outputs = omap3430_dss_supported_outputs,
.supported_color_modes = omap3_dss_supported_color_modes, .supported_color_modes = omap3_dss_supported_color_modes,
.overlay_caps = omap3430_dss_overlay_caps, .overlay_caps = omap3430_dss_overlay_caps,
.clksrc_names = omap3_dss_clk_source_names,
.dss_params = omap3_dss_param_range, .dss_params = omap3_dss_param_range,
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB, .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
.buffer_size_unit = 1, .buffer_size_unit = 1,
@ -696,7 +664,6 @@ static const struct omap_dss_features am43xx_dss_features = {
.supported_outputs = am43xx_dss_supported_outputs, .supported_outputs = am43xx_dss_supported_outputs,
.supported_color_modes = omap3_dss_supported_color_modes, .supported_color_modes = omap3_dss_supported_color_modes,
.overlay_caps = omap3430_dss_overlay_caps, .overlay_caps = omap3430_dss_overlay_caps,
.clksrc_names = omap2_dss_clk_source_names,
.dss_params = am43xx_dss_param_range, .dss_params = am43xx_dss_param_range,
.supported_rotation_types = OMAP_DSS_ROT_DMA, .supported_rotation_types = OMAP_DSS_ROT_DMA,
.buffer_size_unit = 1, .buffer_size_unit = 1,
@ -716,7 +683,6 @@ static const struct omap_dss_features omap3630_dss_features = {
.supported_outputs = omap3630_dss_supported_outputs, .supported_outputs = omap3630_dss_supported_outputs,
.supported_color_modes = omap3_dss_supported_color_modes, .supported_color_modes = omap3_dss_supported_color_modes,
.overlay_caps = omap3630_dss_overlay_caps, .overlay_caps = omap3630_dss_overlay_caps,
.clksrc_names = omap3_dss_clk_source_names,
.dss_params = omap3_dss_param_range, .dss_params = omap3_dss_param_range,
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB, .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
.buffer_size_unit = 1, .buffer_size_unit = 1,
@ -738,7 +704,6 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = {
.supported_outputs = omap4_dss_supported_outputs, .supported_outputs = omap4_dss_supported_outputs,
.supported_color_modes = omap4_dss_supported_color_modes, .supported_color_modes = omap4_dss_supported_color_modes,
.overlay_caps = omap4_dss_overlay_caps, .overlay_caps = omap4_dss_overlay_caps,
.clksrc_names = omap4_dss_clk_source_names,
.dss_params = omap4_dss_param_range, .dss_params = omap4_dss_param_range,
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER, .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
.buffer_size_unit = 16, .buffer_size_unit = 16,
@ -759,7 +724,6 @@ static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = {
.supported_outputs = omap4_dss_supported_outputs, .supported_outputs = omap4_dss_supported_outputs,
.supported_color_modes = omap4_dss_supported_color_modes, .supported_color_modes = omap4_dss_supported_color_modes,
.overlay_caps = omap4_dss_overlay_caps, .overlay_caps = omap4_dss_overlay_caps,
.clksrc_names = omap4_dss_clk_source_names,
.dss_params = omap4_dss_param_range, .dss_params = omap4_dss_param_range,
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER, .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
.buffer_size_unit = 16, .buffer_size_unit = 16,
@ -780,7 +744,6 @@ static const struct omap_dss_features omap4_dss_features = {
.supported_outputs = omap4_dss_supported_outputs, .supported_outputs = omap4_dss_supported_outputs,
.supported_color_modes = omap4_dss_supported_color_modes, .supported_color_modes = omap4_dss_supported_color_modes,
.overlay_caps = omap4_dss_overlay_caps, .overlay_caps = omap4_dss_overlay_caps,
.clksrc_names = omap4_dss_clk_source_names,
.dss_params = omap4_dss_param_range, .dss_params = omap4_dss_param_range,
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER, .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
.buffer_size_unit = 16, .buffer_size_unit = 16,
@ -801,7 +764,6 @@ static const struct omap_dss_features omap5_dss_features = {
.supported_outputs = omap5_dss_supported_outputs, .supported_outputs = omap5_dss_supported_outputs,
.supported_color_modes = omap4_dss_supported_color_modes, .supported_color_modes = omap4_dss_supported_color_modes,
.overlay_caps = omap4_dss_overlay_caps, .overlay_caps = omap4_dss_overlay_caps,
.clksrc_names = omap5_dss_clk_source_names,
.dss_params = omap5_dss_param_range, .dss_params = omap5_dss_param_range,
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER, .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
.buffer_size_unit = 16, .buffer_size_unit = 16,
@ -859,11 +821,6 @@ bool dss_feat_color_mode_supported(enum omap_plane plane,
color_mode; color_mode;
} }
const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id)
{
return omap_current_dss_features->clksrc_names[id];
}
u32 dss_feat_get_buffer_size_unit(void) u32 dss_feat_get_buffer_size_unit(void)
{ {
return omap_current_dss_features->buffer_size_unit; return omap_current_dss_features->buffer_size_unit;

View File

@ -91,7 +91,6 @@ unsigned long dss_feat_get_param_max(enum dss_range_param param);
enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane); enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane);
bool dss_feat_color_mode_supported(enum omap_plane plane, bool dss_feat_color_mode_supported(enum omap_plane plane,
enum omap_color_mode color_mode); enum omap_color_mode color_mode);
const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id);
u32 dss_feat_get_buffer_size_unit(void); /* in bytes */ u32 dss_feat_get_buffer_size_unit(void); /* in bytes */
u32 dss_feat_get_burst_size_unit(void); /* in bytes */ u32 dss_feat_get_burst_size_unit(void); /* in bytes */

View File

@ -240,6 +240,7 @@ struct hdmi_pll_data {
void __iomem *base; void __iomem *base;
struct platform_device *pdev;
struct hdmi_wp_data *wp; struct hdmi_wp_data *wp;
}; };
@ -306,8 +307,6 @@ phys_addr_t hdmi_wp_get_audio_dma_addr(struct hdmi_wp_data *wp);
/* HDMI PLL funcs */ /* HDMI PLL funcs */
void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s); void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s);
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, int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll,
struct hdmi_wp_data *wp); struct hdmi_wp_data *wp);
void hdmi_pll_uninit(struct hdmi_pll_data *hpll); void hdmi_pll_uninit(struct hdmi_pll_data *hpll);

View File

@ -177,7 +177,11 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
if (p->double_pixel) if (p->double_pixel)
pc *= 2; pc *= 2;
hdmi_pll_compute(&hdmi.pll, pc, &hdmi_cinfo); /* DSS_HDMI_TCLK is bitclk / 10 */
pc *= 10;
dss_pll_calc_b(&hdmi.pll.pll, clk_get_rate(hdmi.pll.pll.clkin),
pc, &hdmi_cinfo);
r = dss_pll_enable(&hdmi.pll.pll); r = dss_pll_enable(&hdmi.pll.pll);
if (r) { if (r) {

View File

@ -190,7 +190,11 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
if (p->double_pixel) if (p->double_pixel)
pc *= 2; pc *= 2;
hdmi_pll_compute(&hdmi.pll, pc, &hdmi_cinfo); /* DSS_HDMI_TCLK is bitclk / 10 */
pc *= 10;
dss_pll_calc_b(&hdmi.pll.pll, clk_get_rate(hdmi.pll.pll.clkin),
pc, &hdmi_cinfo);
/* disable and clear irqs */ /* disable and clear irqs */
hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff); hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff);

View File

@ -17,6 +17,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/pm_runtime.h>
#include <video/omapdss.h> #include <video/omapdss.h>
@ -39,71 +40,14 @@ void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s)
DUMPPLL(PLLCTRL_CFG4); DUMPPLL(PLLCTRL_CFG4);
} }
void hdmi_pll_compute(struct hdmi_pll_data *pll,
unsigned long target_tmds, struct dss_pll_clock_info *pi)
{
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, hw->fint_max);
fint = clkin / n;
/* adjust m2 so that the clkdco will be high enough */
min_dco = roundup(hw->clkdco_min, fint);
m2 = DIV_ROUND_UP(min_dco, target_bitclk);
if (m2 == 0)
m2 = 1;
target_clkdco = target_bitclk * m2;
m = target_clkdco / fint;
clkdco = fint * m;
/* adjust clkdco with fractional mf */
if (WARN_ON(target_clkdco - clkdco > fint))
mf = 0;
else
mf = (u32)div_u64(262144ull * (target_clkdco - clkdco), fint);
if (mf > 0)
clkdco += (u32)div_u64((u64)mf * fint, 262144);
clkout = clkdco / m2;
/* sigma-delta */
sd = DIV_ROUND_UP(fint * m, 250000000);
DSSDBG("N = %u, M = %u, M.f = %u, M2 = %u, SD = %u\n",
n, m, mf, m2, sd);
DSSDBG("Fint %lu, clkdco %lu, clkout %lu\n", fint, clkdco, clkout);
pi->n = n;
pi->m = m;
pi->mf = mf;
pi->mX[0] = m2;
pi->sd = sd;
pi->fint = fint;
pi->clkdco = clkdco;
pi->clkout[0] = clkout;
}
static int hdmi_pll_enable(struct dss_pll *dsspll) static int hdmi_pll_enable(struct dss_pll *dsspll)
{ {
struct hdmi_pll_data *pll = container_of(dsspll, struct hdmi_pll_data, pll); struct hdmi_pll_data *pll = container_of(dsspll, struct hdmi_pll_data, pll);
struct hdmi_wp_data *wp = pll->wp; struct hdmi_wp_data *wp = pll->wp;
u16 r = 0; int r;
r = pm_runtime_get_sync(&pll->pdev->dev);
WARN_ON(r < 0);
dss_ctrl_pll_enable(DSS_PLL_HDMI, true); dss_ctrl_pll_enable(DSS_PLL_HDMI, true);
@ -118,10 +62,14 @@ static void hdmi_pll_disable(struct dss_pll *dsspll)
{ {
struct hdmi_pll_data *pll = container_of(dsspll, struct hdmi_pll_data, pll); struct hdmi_pll_data *pll = container_of(dsspll, struct hdmi_pll_data, pll);
struct hdmi_wp_data *wp = pll->wp; struct hdmi_wp_data *wp = pll->wp;
int r;
hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF); hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF);
dss_ctrl_pll_enable(DSS_PLL_HDMI, false); dss_ctrl_pll_enable(DSS_PLL_HDMI, false);
r = pm_runtime_put_sync(&pll->pdev->dev);
WARN_ON(r < 0 && r != -ENOSYS);
} }
static const struct dss_pll_ops dsi_pll_ops = { static const struct dss_pll_ops dsi_pll_ops = {
@ -131,6 +79,8 @@ static const struct dss_pll_ops dsi_pll_ops = {
}; };
static const struct dss_pll_hw dss_omap4_hdmi_pll_hw = { static const struct dss_pll_hw dss_omap4_hdmi_pll_hw = {
.type = DSS_PLL_TYPE_B,
.n_max = 255, .n_max = 255,
.m_min = 20, .m_min = 20,
.m_max = 4095, .m_max = 4095,
@ -154,6 +104,8 @@ static const struct dss_pll_hw dss_omap4_hdmi_pll_hw = {
}; };
static const struct dss_pll_hw dss_omap5_hdmi_pll_hw = { static const struct dss_pll_hw dss_omap5_hdmi_pll_hw = {
.type = DSS_PLL_TYPE_B,
.n_max = 255, .n_max = 255,
.m_min = 20, .m_min = 20,
.m_max = 2045, .m_max = 2045,
@ -225,6 +177,7 @@ int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll,
int r; int r;
struct resource *res; struct resource *res;
pll->pdev = pdev;
pll->wp = wp; pll->wp = wp;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll");

View File

@ -76,6 +76,59 @@ struct dss_pll *dss_pll_find(const char *name)
return NULL; return NULL;
} }
struct dss_pll *dss_pll_find_by_src(enum dss_clk_source src)
{
struct dss_pll *pll;
switch (src) {
default:
case DSS_CLK_SRC_FCK:
return NULL;
case DSS_CLK_SRC_HDMI_PLL:
return dss_pll_find("hdmi");
case DSS_CLK_SRC_PLL1_1:
case DSS_CLK_SRC_PLL1_2:
case DSS_CLK_SRC_PLL1_3:
pll = dss_pll_find("dsi0");
if (!pll)
pll = dss_pll_find("video0");
return pll;
case DSS_CLK_SRC_PLL2_1:
case DSS_CLK_SRC_PLL2_2:
case DSS_CLK_SRC_PLL2_3:
pll = dss_pll_find("dsi1");
if (!pll)
pll = dss_pll_find("video1");
return pll;
}
}
unsigned dss_pll_get_clkout_idx_for_src(enum dss_clk_source src)
{
switch (src) {
case DSS_CLK_SRC_HDMI_PLL:
return 0;
case DSS_CLK_SRC_PLL1_1:
case DSS_CLK_SRC_PLL2_1:
return 0;
case DSS_CLK_SRC_PLL1_2:
case DSS_CLK_SRC_PLL2_2:
return 1;
case DSS_CLK_SRC_PLL1_3:
case DSS_CLK_SRC_PLL2_3:
return 2;
default:
return 0;
}
}
int dss_pll_enable(struct dss_pll *pll) int dss_pll_enable(struct dss_pll *pll)
{ {
int r; int r;
@ -129,7 +182,7 @@ int dss_pll_set_config(struct dss_pll *pll, const struct dss_pll_clock_info *cin
return 0; return 0;
} }
bool dss_pll_hsdiv_calc(const struct dss_pll *pll, unsigned long clkdco, bool dss_pll_hsdiv_calc_a(const struct dss_pll *pll, unsigned long clkdco,
unsigned long out_min, unsigned long out_max, unsigned long out_min, unsigned long out_max,
dss_hsdiv_calc_func func, void *data) dss_hsdiv_calc_func func, void *data)
{ {
@ -154,7 +207,11 @@ bool dss_pll_hsdiv_calc(const struct dss_pll *pll, unsigned long clkdco,
return false; return false;
} }
bool dss_pll_calc(const struct dss_pll *pll, unsigned long clkin, /*
* clkdco = clkin / n * m * 2
* clkoutX = clkdco / mX
*/
bool dss_pll_calc_a(const struct dss_pll *pll, unsigned long clkin,
unsigned long pll_min, unsigned long pll_max, unsigned long pll_min, unsigned long pll_max,
dss_pll_calc_func func, void *data) dss_pll_calc_func func, void *data)
{ {
@ -195,6 +252,71 @@ bool dss_pll_calc(const struct dss_pll *pll, unsigned long clkin,
return false; return false;
} }
/*
* This calculates a PLL config that will provide the target_clkout rate
* for clkout. Additionally clkdco rate will be the same as clkout rate
* when clkout rate is >= min_clkdco.
*
* clkdco = clkin / n * m + clkin / n * mf / 262144
* clkout = clkdco / m2
*/
bool dss_pll_calc_b(const struct dss_pll *pll, unsigned long clkin,
unsigned long target_clkout, struct dss_pll_clock_info *cinfo)
{
unsigned long fint, clkdco, clkout;
unsigned long target_clkdco;
unsigned long min_dco;
unsigned n, m, mf, m2, sd;
const struct dss_pll_hw *hw = pll->hw;
DSSDBG("clkin %lu, target clkout %lu\n", clkin, target_clkout);
/* Fint */
n = DIV_ROUND_UP(clkin, hw->fint_max);
fint = clkin / n;
/* adjust m2 so that the clkdco will be high enough */
min_dco = roundup(hw->clkdco_min, fint);
m2 = DIV_ROUND_UP(min_dco, target_clkout);
if (m2 == 0)
m2 = 1;
target_clkdco = target_clkout * m2;
m = target_clkdco / fint;
clkdco = fint * m;
/* adjust clkdco with fractional mf */
if (WARN_ON(target_clkdco - clkdco > fint))
mf = 0;
else
mf = (u32)div_u64(262144ull * (target_clkdco - clkdco), fint);
if (mf > 0)
clkdco += (u32)div_u64((u64)mf * fint, 262144);
clkout = clkdco / m2;
/* sigma-delta */
sd = DIV_ROUND_UP(fint * m, 250000000);
DSSDBG("N = %u, M = %u, M.f = %u, M2 = %u, SD = %u\n",
n, m, mf, m2, sd);
DSSDBG("Fint %lu, clkdco %lu, clkout %lu\n", fint, clkdco, clkout);
cinfo->n = n;
cinfo->m = m;
cinfo->mf = mf;
cinfo->mX[0] = m2;
cinfo->sd = sd;
cinfo->fint = fint;
cinfo->clkdco = clkdco;
cinfo->clkout[0] = clkout;
return true;
}
static int wait_for_bit_change(void __iomem *reg, int bitnum, int value) static int wait_for_bit_change(void __iomem *reg, int bitnum, int value)
{ {
unsigned long timeout; unsigned long timeout;

View File

@ -108,6 +108,8 @@ static const struct dss_pll_ops dss_pll_ops = {
}; };
static const struct dss_pll_hw dss_dra7_video_pll_hw = { static const struct dss_pll_hw dss_dra7_video_pll_hw = {
.type = DSS_PLL_TYPE_A,
.n_max = (1 << 8) - 1, .n_max = (1 << 8) - 1,
.m_max = (1 << 12) - 1, .m_max = (1 << 12) - 1,
.mX_max = (1 << 5) - 1, .mX_max = (1 << 5) - 1,
@ -124,6 +126,10 @@ static const struct dss_pll_hw dss_dra7_video_pll_hw = {
.mX_lsb[0] = 21, .mX_lsb[0] = 21,
.mX_msb[1] = 30, .mX_msb[1] = 30,
.mX_lsb[1] = 26, .mX_lsb[1] = 26,
.mX_msb[2] = 4,
.mX_lsb[2] = 0,
.mX_msb[3] = 9,
.mX_lsb[3] = 5,
.has_refsel = true, .has_refsel = true,
}; };

View File

@ -73,6 +73,17 @@
#define FLD_MOD(orig, val, start, end) \ #define FLD_MOD(orig, val, start, end) \
(((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
enum omap_dss_clk_source {
OMAP_DSS_CLK_SRC_FCK = 0, /* OMAP2/3: DSS1_ALWON_FCLK
* OMAP4: DSS_FCLK */
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, /* OMAP3: DSI1_PLL_FCLK
* OMAP4: PLL1_CLK1 */
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, /* OMAP3: DSI2_PLL_FCLK
* OMAP4: PLL1_CLK2 */
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC, /* OMAP4: PLL2_CLK1 */
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI, /* OMAP4: PLL2_CLK2 */
};
enum dss_io_pad_mode { enum dss_io_pad_mode {
DSS_IO_PAD_MODE_RESET, DSS_IO_PAD_MODE_RESET,
DSS_IO_PAD_MODE_RFBI, DSS_IO_PAD_MODE_RFBI,

View File

@ -69,7 +69,6 @@ int dss_init_overlay_managers(void)
break; break;
} }
mgr->caps = 0;
mgr->supported_displays = mgr->supported_displays =
dss_feat_get_supported_displays(mgr->id); dss_feat_get_supported_displays(mgr->id);
mgr->supported_outputs = mgr->supported_outputs =

View File

@ -195,25 +195,6 @@ enum omap_overlay_caps {
OMAP_DSS_OVL_CAP_REPLICATION = 1 << 5, OMAP_DSS_OVL_CAP_REPLICATION = 1 << 5,
}; };
enum omap_overlay_manager_caps {
OMAP_DSS_DUMMY_VALUE, /* add a dummy value to prevent compiler error */
};
enum omap_dss_clk_source {
OMAP_DSS_CLK_SRC_FCK = 0, /* OMAP2/3: DSS1_ALWON_FCLK
* OMAP4: DSS_FCLK */
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, /* OMAP3: DSI1_PLL_FCLK
* OMAP4: PLL1_CLK1 */
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, /* OMAP3: DSI2_PLL_FCLK
* OMAP4: PLL1_CLK2 */
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC, /* OMAP4: PLL2_CLK1 */
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI, /* OMAP4: PLL2_CLK2 */
};
enum omap_hdmi_flags {
OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP = 1 << 0,
};
enum omap_dss_output_id { enum omap_dss_output_id {
OMAP_DSS_OUTPUT_DPI = 1 << 0, OMAP_DSS_OUTPUT_DPI = 1 << 0,
OMAP_DSS_OUTPUT_DBI = 1 << 1, OMAP_DSS_OUTPUT_DBI = 1 << 1,
@ -463,7 +444,6 @@ struct omap_overlay_manager {
/* static fields */ /* static fields */
const char *name; const char *name;
enum omap_channel id; enum omap_channel id;
enum omap_overlay_manager_caps caps;
struct list_head overlays; struct list_head overlays;
enum omap_display_type supported_displays; enum omap_display_type supported_displays;
enum omap_dss_output_id supported_outputs; enum omap_dss_output_id supported_outputs;