staticint check_ext_bounds(struct device *dev, conststruct ccs_pll *pll)
{ if (!(pll->flags & CCS_PLL_FLAG_FIFO_DERATING) &&
pll->pixel_rate_pixel_array > pll->pixel_rate_csi) {
dev_dbg(dev, "device does not support derating\n"); return -EINVAL;
}
if (!(pll->flags & CCS_PLL_FLAG_FIFO_OVERRATING) &&
pll->pixel_rate_pixel_array < pll->pixel_rate_csi) {
dev_dbg(dev, "device does not support overrating\n"); return -EINVAL;
}
return 0;
}
staticvoid
ccs_pll_find_vt_sys_div(struct device *dev, conststruct ccs_pll_limits *lim, struct ccs_pll *pll, struct ccs_pll_branch_fr *pll_fr,
u16 min_vt_div, u16 max_vt_div,
u16 *min_sys_div, u16 *max_sys_div)
{ /* * Find limits for sys_clk_div. Not all values are possible with all * values of pix_clk_div.
*/
*min_sys_div = lim->vt_bk.min_sys_clk_div;
dev_dbg(dev, "min_sys_div: %u\n", *min_sys_div);
*min_sys_div = max_t(u16, *min_sys_div,
DIV_ROUND_UP(min_vt_div,
lim->vt_bk.max_pix_clk_div));
dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %u\n", *min_sys_div);
*min_sys_div = max_t(u16, *min_sys_div,
pll_fr->pll_op_clk_freq_hz
/ lim->vt_bk.max_sys_clk_freq_hz);
dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %u\n", *min_sys_div);
*min_sys_div = clk_div_even_up(*min_sys_div);
dev_dbg(dev, "min_sys_div: one or even: %u\n", *min_sys_div);
if (pix_div < lim_bk->min_pix_clk_div ||
pix_div > lim_bk->max_pix_clk_div) {
dev_dbg(dev, "pix_div %u too small or too big (%u--%u)\n",
pix_div,
lim_bk->min_pix_clk_div,
lim_bk->max_pix_clk_div); continue;
}
/* Make sure PLL input frequency is within limits */
max_pre_pll_clk_div =
min_t(u16, max_pre_pll_clk_div,
DIV_ROUND_UP(pll->ext_clk_freq_hz,
lim_fr->min_pll_ip_clk_freq_hz));
if (pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) goto out_calc_pixel_rate;
/* * Find out whether a sensor supports derating. If it does not, VT and * OP domains are required to run at the same pixel rate.
*/ if (!(pll->flags & CCS_PLL_FLAG_FIFO_DERATING)) {
min_vt_div =
op_pll_bk->sys_clk_div * op_pll_bk->pix_clk_div
* pll->vt_lanes * phy_const / pll->op_lanes
/ (PHY_CONST_DIV << op_pix_ddr(pll->flags));
} else { /* * Some sensors perform analogue binning and some do this * digitally. The ones doing this digitally can be roughly be * found out using this formula. The ones doing this digitally * should run at higher clock rate, so smaller divisor is used * on video timing side.
*/ if (lim->min_line_length_pck_bin > lim->min_line_length_pck
/ pll->binning_horizontal)
vt_op_binning_div = pll->binning_horizontal; else
vt_op_binning_div = 1;
dev_dbg(dev, "vt_op_binning_div: %u\n", vt_op_binning_div);
/* * Profile 2 supports vt_pix_clk_div E [4, 10] * * Horizontal binning can be used as a base for difference in * divisors. One must make sure that horizontal blanking is * enough to accommodate the CSI-2 sync codes. * * Take scaling factor and number of VT lanes into account as well. * * Find absolute limits for the factor of vt divider.
*/
dev_dbg(dev, "scale_m: %u\n", pll->scale_m);
min_vt_div =
DIV_ROUND_UP(pll->bits_per_pixel
* op_pll_bk->sys_clk_div * pll->scale_n
* pll->vt_lanes * phy_const,
(pll->flags &
CCS_PLL_FLAG_LANE_SPEED_MODEL ?
pll->csi2.lanes : 1)
* vt_op_binning_div * pll->scale_m
* PHY_CONST_DIV << op_pix_ddr(pll->flags));
}
/* * Find pix_div such that a legal pix_div * sys_div results * into a value which is not smaller than div, the desired * divisor.
*/ for (vt_div = min_vt_div; vt_div <= max_vt_div; vt_div++) {
u16 __max_sys_div = vt_div & 1 ? 1 : max_sys_div;
if (pix_div < lim->vt_bk.min_pix_clk_div
|| pix_div > lim->vt_bk.max_pix_clk_div) {
dev_dbg(dev, "pix_div %u too small or too big (%u--%u)\n",
pix_div,
lim->vt_bk.min_pix_clk_div,
lim->vt_bk.max_pix_clk_div); continue;
}
rounded_div = roundup(vt_div, best_pix_div);
/* Check if this one is better. */ if (pix_div * sys_div <= rounded_div)
best_pix_div = pix_div;
/* Bail out if we've already found the best value. */ if (vt_div == rounded_div) break;
} if (best_pix_div < SHRT_MAX >> 1) break;
} if (best_pix_div == SHRT_MAX >> 1) return -EINVAL;
/* * Heuristically guess the PLL tree for a given common multiplier and * divisor. Begin with the operational timing and continue to video * timing once operational timing has been verified. * * @mul is the PLL multiplier and @div is the common divisor * (pre_pll_clk_div and op_sys_clk_div combined). The final PLL * multiplier will be a multiple of @mul. * * @return Zero on success, error code on error.
*/ staticint
ccs_pll_calculate_op(struct device *dev, conststruct ccs_pll_limits *lim, conststruct ccs_pll_branch_limits_fr *op_lim_fr, conststruct ccs_pll_branch_limits_bk *op_lim_bk, struct ccs_pll *pll, struct ccs_pll_branch_fr *op_pll_fr, struct ccs_pll_branch_bk *op_pll_bk, u32 mul,
u32 div, u32 op_sys_clk_freq_hz_sdr, u32 l, bool cphy, u32 phy_const)
{ /* * Higher multipliers (and divisors) are often required than * necessitated by the external clock and the output clocks. * There are limits for all values in the clock tree. These * are the minimum and maximum multiplier for mul.
*/
u32 more_mul_min, more_mul_max;
u32 more_mul_factor;
u32 i;
/* * Get pre_pll_clk_div so that our pll_op_clk_freq_hz won't be * too high.
*/
dev_dbg(dev, "op_pre_pll_clk_div %u\n", op_pll_fr->pre_pll_clk_div);
/* Don't go above max pll multiplier. */
more_mul_max = op_lim_fr->max_pll_multiplier / mul;
dev_dbg(dev, "more_mul_max: max_op_pll_multiplier check: %u\n",
more_mul_max); /* Don't go above max pll op frequency. */
more_mul_max =
min_t(u32,
more_mul_max,
op_lim_fr->max_pll_op_clk_freq_hz
/ (pll->ext_clk_freq_hz /
op_pll_fr->pre_pll_clk_div * mul));
dev_dbg(dev, "more_mul_max: max_pll_op_clk_freq_hz check: %u\n",
more_mul_max); /* Don't go above the division capability of op sys clock divider. */
more_mul_max = min(more_mul_max,
op_lim_bk->max_sys_clk_div * op_pll_fr->pre_pll_clk_div
/ div);
dev_dbg(dev, "more_mul_max: max_op_sys_clk_div check: %u\n",
more_mul_max); /* Ensure we won't go above max_pll_multiplier. */
more_mul_max = min(more_mul_max, op_lim_fr->max_pll_multiplier / mul);
dev_dbg(dev, "more_mul_max: min_pll_multiplier check: %u\n",
more_mul_max);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.