Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 343882
b: refs/heads/master
c: 6de1b14
h: refs/heads/master
v: v3
  • Loading branch information
Sakari Ailus authored and Mauro Carvalho Chehab committed Oct 29, 2012
1 parent 2226dfd commit 83e2e45
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 59 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c2ebca00324ce7b89f756d5e182a5b3db938a4c9
refs/heads/master: 6de1b143a45d3c4b8ad277b484e0d14df0d30d63
131 changes: 73 additions & 58 deletions trunk/drivers/media/i2c/smiapp-pll.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ static int bounds_check(struct device *dev, uint32_t val,
if (val >= min && val <= max)
return 0;

dev_warn(dev, "%s out of bounds: %d (%d--%d)\n", str, val, min, max);
dev_dbg(dev, "%s out of bounds: %d (%d--%d)\n", str, val, min, max);

return -EINVAL;
}
Expand Down Expand Up @@ -87,69 +87,21 @@ static void print_pll(struct device *dev, struct smiapp_pll *pll)
dev_dbg(dev, "vt_pix_clk_freq_hz \t%d\n", pll->vt_pix_clk_freq_hz);
}

int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
struct smiapp_pll *pll)
static int __smiapp_pll_calculate(struct device *dev,
struct smiapp_pll_limits *limits,
struct smiapp_pll *pll, uint32_t mul,
uint32_t div, uint32_t lane_op_clock_ratio)
{
uint32_t sys_div;
uint32_t best_pix_div = INT_MAX >> 1;
uint32_t vt_op_binning_div;
uint32_t lane_op_clock_ratio;
uint32_t mul, div;
uint32_t more_mul_min, more_mul_max;
uint32_t more_mul_factor;
uint32_t min_vt_div, max_vt_div, vt_div;
uint32_t min_sys_div, max_sys_div;
unsigned int i;
int rval;

if (pll->flags & SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE)
lane_op_clock_ratio = pll->lanes;
else
lane_op_clock_ratio = 1;
dev_dbg(dev, "lane_op_clock_ratio: %d\n", lane_op_clock_ratio);

dev_dbg(dev, "binning: %dx%d\n", pll->binning_horizontal,
pll->binning_vertical);

/* CSI transfers 2 bits per clock per lane; thus times 2 */
pll->pll_op_clk_freq_hz = pll->link_freq * 2
* (pll->lanes / lane_op_clock_ratio);

/* Figure out limits for pre-pll divider based on extclk */
dev_dbg(dev, "min / max pre_pll_clk_div: %d / %d\n",
limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);
limits->max_pre_pll_clk_div =
min_t(uint16_t, limits->max_pre_pll_clk_div,
clk_div_even(pll->ext_clk_freq_hz /
limits->min_pll_ip_freq_hz));
limits->min_pre_pll_clk_div =
max_t(uint16_t, limits->min_pre_pll_clk_div,
clk_div_even_up(
DIV_ROUND_UP(pll->ext_clk_freq_hz,
limits->max_pll_ip_freq_hz)));
dev_dbg(dev, "pre-pll check: min / max pre_pll_clk_div: %d / %d\n",
limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);

i = gcd(pll->pll_op_clk_freq_hz, pll->ext_clk_freq_hz);
mul = div_u64(pll->pll_op_clk_freq_hz, i);
div = pll->ext_clk_freq_hz / i;
dev_dbg(dev, "mul %d / div %d\n", mul, div);

limits->min_pre_pll_clk_div =
max_t(uint16_t, limits->min_pre_pll_clk_div,
clk_div_even_up(
DIV_ROUND_UP(mul * pll->ext_clk_freq_hz,
limits->max_pll_op_freq_hz)));
dev_dbg(dev, "pll_op check: min / max pre_pll_clk_div: %d / %d\n",
limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);

if (limits->min_pre_pll_clk_div > limits->max_pre_pll_clk_div) {
dev_err(dev, "unable to compute pre_pll divisor\n");
return -EINVAL;
}

pll->pre_pll_clk_div = limits->min_pre_pll_clk_div;

/*
* Get pre_pll_clk_div so that our pll_op_clk_freq_hz won't be
* too high.
Expand Down Expand Up @@ -193,8 +145,8 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
more_mul_min);

if (more_mul_min > more_mul_max) {
dev_warn(dev,
"unable to compute more_mul_min and more_mul_max\n");
dev_dbg(dev,
"unable to compute more_mul_min and more_mul_max\n");
return -EINVAL;
}

Expand All @@ -209,7 +161,7 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,

dev_dbg(dev, "final more_mul: %d\n", i);
if (i > more_mul_max) {
dev_warn(dev, "final more_mul is bad, max %d\n", more_mul_max);
dev_dbg(dev, "final more_mul is bad, max %d\n", more_mul_max);
return -EINVAL;
}

Expand Down Expand Up @@ -354,8 +306,6 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
pll->pixel_rate_csi =
pll->op_pix_clk_freq_hz * lane_op_clock_ratio;

print_pll(dev, pll);

rval = bounds_check(dev, pll->pre_pll_clk_div,
limits->min_pre_pll_clk_div,
limits->max_pre_pll_clk_div, "pre_pll_clk_div");
Expand Down Expand Up @@ -411,6 +361,71 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,

return rval;
}

int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
struct smiapp_pll *pll)
{
uint32_t lane_op_clock_ratio;
uint32_t mul, div;
unsigned int i;
int rval = -EINVAL;

if (pll->flags & SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE)
lane_op_clock_ratio = pll->lanes;
else
lane_op_clock_ratio = 1;
dev_dbg(dev, "lane_op_clock_ratio: %d\n", lane_op_clock_ratio);

dev_dbg(dev, "binning: %dx%d\n", pll->binning_horizontal,
pll->binning_vertical);

/* CSI transfers 2 bits per clock per lane; thus times 2 */
pll->pll_op_clk_freq_hz = pll->link_freq * 2
* (pll->lanes / lane_op_clock_ratio);

/* Figure out limits for pre-pll divider based on extclk */
dev_dbg(dev, "min / max pre_pll_clk_div: %d / %d\n",
limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);
limits->max_pre_pll_clk_div =
min_t(uint16_t, limits->max_pre_pll_clk_div,
clk_div_even(pll->ext_clk_freq_hz /
limits->min_pll_ip_freq_hz));
limits->min_pre_pll_clk_div =
max_t(uint16_t, limits->min_pre_pll_clk_div,
clk_div_even_up(
DIV_ROUND_UP(pll->ext_clk_freq_hz,
limits->max_pll_ip_freq_hz)));
dev_dbg(dev, "pre-pll check: min / max pre_pll_clk_div: %d / %d\n",
limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);

i = gcd(pll->pll_op_clk_freq_hz, pll->ext_clk_freq_hz);
mul = div_u64(pll->pll_op_clk_freq_hz, i);
div = pll->ext_clk_freq_hz / i;
dev_dbg(dev, "mul %d / div %d\n", mul, div);

limits->min_pre_pll_clk_div =
max_t(uint16_t, limits->min_pre_pll_clk_div,
clk_div_even_up(
DIV_ROUND_UP(mul * pll->ext_clk_freq_hz,
limits->max_pll_op_freq_hz)));
dev_dbg(dev, "pll_op check: min / max pre_pll_clk_div: %d / %d\n",
limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);

for (pll->pre_pll_clk_div = limits->min_pre_pll_clk_div;
pll->pre_pll_clk_div <= limits->max_pre_pll_clk_div;
pll->pre_pll_clk_div += 2 - (pll->pre_pll_clk_div & 1)) {
rval = __smiapp_pll_calculate(dev, limits, pll, mul, div,
lane_op_clock_ratio);
if (rval)
continue;

print_pll(dev, pll);
return 0;
}

dev_info(dev, "unable to compute pre_pll divisor\n");
return rval;
}
EXPORT_SYMBOL_GPL(smiapp_pll_calculate);

MODULE_AUTHOR("Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>");
Expand Down

0 comments on commit 83e2e45

Please sign in to comment.