Skip to content

Commit

Permalink
Merge OMAP5 DSS changes to omapdss
Browse files Browse the repository at this point in the history
This series adds basic OMAP5 DSS functionality, mainly related to DSS core, DPI
and DSI.

* omap5-dss:
  OMAPDSS: DSI: make OMAP2_DSS_DSI depend on ARCH_OMAP5
  OMAPDSS: DSI: Add code to disable PHY DCC
  OMAPDSS: DSI: Add new linebuffer size for OMAP5
  OMAPDSS: DSI: Add FEAT_DSI_PLL_REFSEL
  OMAPDSS: DSI: Add FEAT_DSI_PLL_SELFREQDCO
  OMAPDSS: Add support for DPI source selection
  OMAPDSS: move dss feats to the end of dss.c
  OMAPDSS: Add basic omap5 features to dss and dispc
  OMAPDSS: DSI: improve DSI clock calcs for DISPC
  • Loading branch information
Tomi Valkeinen committed Sep 25, 2012
2 parents c0ca7c3 + 9958858 commit 406f7b8
Show file tree
Hide file tree
Showing 8 changed files with 337 additions and 60 deletions.
2 changes: 1 addition & 1 deletion drivers/video/omap2/dss/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ config OMAP2_DSS_SDI

config OMAP2_DSS_DSI
bool "DSI support"
depends on ARCH_OMAP3 || ARCH_OMAP4
depends on ARCH_OMAP3 || ARCH_OMAP4 || ARCH_OMAP5
default n
help
MIPI DSI (Display Serial Interface) support.
Expand Down
2 changes: 2 additions & 0 deletions drivers/video/omap2/dss/dispc.c
Original file line number Diff line number Diff line change
Expand Up @@ -3829,6 +3829,8 @@ static int __init dispc_init_features(struct device *dev)
src = &omap34xx_rev3_0_dispc_feats;
} else if (cpu_is_omap44xx()) {
src = &omap44xx_dispc_feats;
} else if (soc_is_omap54xx()) {
src = &omap44xx_dispc_feats;
} else {
return -ENODEV;
}
Expand Down
5 changes: 5 additions & 0 deletions drivers/video/omap2/dss/dpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,10 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
if (r)
goto err_get_dispc;

r = dss_dpi_select_source(dssdev->channel);
if (r)
goto err_src_sel;

if (dpi_use_dsi_pll(dssdev)) {
r = dsi_runtime_get(dpi.dsidev);
if (r)
Expand Down Expand Up @@ -237,6 +241,7 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
if (dpi_use_dsi_pll(dssdev))
dsi_runtime_put(dpi.dsidev);
err_get_dsi:
err_src_sel:
dispc_runtime_put();
err_get_dispc:
if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
Expand Down
167 changes: 132 additions & 35 deletions drivers/video/omap2/dss/dsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1454,26 +1454,17 @@ int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev,
}

static int dsi_pll_calc_ddrfreq(struct platform_device *dsidev,
unsigned long req_clk, struct dsi_clock_info *cinfo)
unsigned long req_clkin4ddr, struct dsi_clock_info *cinfo)
{
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
struct dsi_clock_info cur, best;
unsigned long dss_sys_clk, max_dss_fck, max_dsi_fck;
unsigned long req_clkin4ddr;

DSSDBG("dsi_pll_calc_ddrfreq\n");

dss_sys_clk = clk_get_rate(dsi->sys_clk);

max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
max_dsi_fck = dss_feat_get_param_max(FEAT_PARAM_DSI_FCK);

memset(&best, 0, sizeof(best));
memset(&cur, 0, sizeof(cur));

cur.clkin = dss_sys_clk;

req_clkin4ddr = req_clk * 4;
cur.clkin = clk_get_rate(dsi->sys_clk);

for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) {
cur.fint = cur.clkin / cur.regn;
Expand Down Expand Up @@ -1503,18 +1494,107 @@ static int dsi_pll_calc_ddrfreq(struct platform_device *dsidev,
}
}
found:
best.regm_dispc = DIV_ROUND_UP(best.clkin4ddr, max_dss_fck);
best.dsi_pll_hsdiv_dispc_clk = best.clkin4ddr / best.regm_dispc;

best.regm_dsi = DIV_ROUND_UP(best.clkin4ddr, max_dsi_fck);
best.dsi_pll_hsdiv_dsi_clk = best.clkin4ddr / best.regm_dsi;

if (cinfo)
*cinfo = best;

return 0;
}

static void dsi_pll_calc_dsi_fck(struct platform_device *dsidev,
struct dsi_clock_info *cinfo)
{
unsigned long max_dsi_fck;

max_dsi_fck = dss_feat_get_param_max(FEAT_PARAM_DSI_FCK);

cinfo->regm_dsi = DIV_ROUND_UP(cinfo->clkin4ddr, max_dsi_fck);
cinfo->dsi_pll_hsdiv_dsi_clk = cinfo->clkin4ddr / cinfo->regm_dsi;
}

static int dsi_pll_calc_dispc_fck(struct platform_device *dsidev,
unsigned long req_pck, struct dsi_clock_info *cinfo,
struct dispc_clock_info *dispc_cinfo)
{
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
unsigned regm_dispc, best_regm_dispc;
unsigned long dispc_clk, best_dispc_clk;
int min_fck_per_pck;
unsigned long max_dss_fck;
struct dispc_clock_info best_dispc;
bool match;

max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);

min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;

if (min_fck_per_pck &&
req_pck * min_fck_per_pck > max_dss_fck) {
DSSERR("Requested pixel clock not possible with the current "
"OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
"the constraint off.\n");
min_fck_per_pck = 0;
}

retry:
best_regm_dispc = 0;
best_dispc_clk = 0;
memset(&best_dispc, 0, sizeof(best_dispc));
match = false;

for (regm_dispc = 1; regm_dispc < dsi->regm_dispc_max; ++regm_dispc) {
struct dispc_clock_info cur_dispc;

dispc_clk = cinfo->clkin4ddr / regm_dispc;

/* this will narrow down the search a bit,
* but still give pixclocks below what was
* requested */
if (dispc_clk < req_pck)
break;

if (dispc_clk > max_dss_fck)
continue;

if (min_fck_per_pck && dispc_clk < req_pck * min_fck_per_pck)
continue;

match = true;

dispc_find_clk_divs(req_pck, dispc_clk, &cur_dispc);

if (abs(cur_dispc.pck - req_pck) <
abs(best_dispc.pck - req_pck)) {
best_regm_dispc = regm_dispc;
best_dispc_clk = dispc_clk;
best_dispc = cur_dispc;

if (cur_dispc.pck == req_pck)
goto found;
}
}

if (!match) {
if (min_fck_per_pck) {
DSSERR("Could not find suitable clock settings.\n"
"Turning FCK/PCK constraint off and"
"trying again.\n");
min_fck_per_pck = 0;
goto retry;
}

DSSERR("Could not find suitable clock settings.\n");

return -EINVAL;
}
found:
cinfo->regm_dispc = best_regm_dispc;
cinfo->dsi_pll_hsdiv_dispc_clk = best_dispc_clk;

*dispc_cinfo = best_dispc;

return 0;
}

int dsi_pll_set_clock_div(struct platform_device *dsidev,
struct dsi_clock_info *cinfo)
{
Expand Down Expand Up @@ -1591,21 +1671,27 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,

BUG_ON(cinfo->fint < dsi->fint_min || cinfo->fint > dsi->fint_max);

l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);

if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) {
f = cinfo->fint < 1000000 ? 0x3 :
cinfo->fint < 1250000 ? 0x4 :
cinfo->fint < 1500000 ? 0x5 :
cinfo->fint < 1750000 ? 0x6 :
0x7;
}

l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);

if (dss_has_feature(FEAT_DSI_PLL_FREQSEL))
l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */
} else if (dss_has_feature(FEAT_DSI_PLL_SELFREQDCO)) {
f = cinfo->clkin4ddr < 1000000000 ? 0x2 : 0x4;

l = FLD_MOD(l, f, 4, 1); /* PLL_SELFREQDCO */
}

l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */
l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */
if (dss_has_feature(FEAT_DSI_PLL_REFSEL))
l = FLD_MOD(l, 3, 22, 21); /* REF_SYSCLK = sysclk */
dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l);

REG_FLD_MOD(dsidev, DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */
Expand Down Expand Up @@ -2069,6 +2155,8 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
return 1194 * 3; /* 1194x24 bits */
case 6:
return 1365 * 3; /* 1365x24 bits */
case 7:
return 1920 * 3; /* 1920x24 bits */
default:
BUG();
return 0;
Expand Down Expand Up @@ -2204,6 +2292,13 @@ static void dsi_cio_timings(struct platform_device *dsidev)
r = FLD_MOD(r, tlpx_half, 22, 16);
r = FLD_MOD(r, tclk_trail, 15, 8);
r = FLD_MOD(r, tclk_zero, 7, 0);

if (dss_has_feature(FEAT_DSI_PHY_DCC)) {
r = FLD_MOD(r, 0, 21, 21); /* DCCEN = disable */
r = FLD_MOD(r, 1, 22, 22); /* CLKINP_DIVBY2EN = enable */
r = FLD_MOD(r, 1, 23, 23); /* CLKINP_SEL = enable */
}

dsi_write_reg(dsidev, DSI_DSIPHY_CFG1, r);

r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2);
Expand Down Expand Up @@ -4188,33 +4283,35 @@ int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,

mutex_lock(&dsi->lock);

r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk, &cinfo);
/* Calculate PLL output clock */
r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk * 4, &cinfo);
if (r)
goto err;

dssdev->clocks.dsi.regn = cinfo.regn;
dssdev->clocks.dsi.regm = cinfo.regm;
dssdev->clocks.dsi.regm_dispc = cinfo.regm_dispc;
dssdev->clocks.dsi.regm_dsi = cinfo.regm_dsi;
/* Calculate PLL's DSI clock */
dsi_pll_calc_dsi_fck(dsidev, &cinfo);

/* Calculate PLL's DISPC clock and pck & lck divs */
pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp;
DSSDBG("finding dispc dividers for pck %lu\n", pck);
r = dsi_pll_calc_dispc_fck(dsidev, pck, &cinfo, &dispc_cinfo);
if (r)
goto err;

/* Calculate LP clock */
dsi_fclk = cinfo.dsi_pll_hsdiv_dsi_clk;
lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk * 2);

dssdev->clocks.dsi.lp_clk_div = lp_clk_div;

/* pck = TxByteClkHS * datalanes * 8 / bitsperpixel */

pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp;

DSSDBG("finding dispc dividers for pck %lu\n", pck);
dssdev->clocks.dsi.regn = cinfo.regn;
dssdev->clocks.dsi.regm = cinfo.regm;
dssdev->clocks.dsi.regm_dispc = cinfo.regm_dispc;
dssdev->clocks.dsi.regm_dsi = cinfo.regm_dsi;

dispc_find_clk_divs(pck, cinfo.dsi_pll_hsdiv_dispc_clk, &dispc_cinfo);
dssdev->clocks.dsi.lp_clk_div = lp_clk_div;

dssdev->clocks.dispc.channel.lck_div = dispc_cinfo.lck_div;
dssdev->clocks.dispc.channel.pck_div = dispc_cinfo.pck_div;


dssdev->clocks.dispc.dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK;

dssdev->clocks.dispc.channel.lcd_clk_src =
Expand Down
Loading

0 comments on commit 406f7b8

Please sign in to comment.