diff options
-rw-r--r-- | drivers/media/i2c/ccs-pll.c | 26 | ||||
-rw-r--r-- | drivers/media/i2c/ccs-pll.h | 1 | ||||
-rw-r--r-- | drivers/media/i2c/ccs/ccs-core.c | 4 |
3 files changed, 23 insertions, 8 deletions
diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index 60ab0c043c7a..e3a6493fd601 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -294,11 +294,11 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, * 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(op_pll_bk->pix_clk_div - * op_pll_bk->sys_clk_div * pll->scale_n - * pll->vt_lanes * l, - pll->op_lanes * vt_op_binning_div - * 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, + (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ? + pll->csi2.lanes : 1) + * vt_op_binning_div * pll->scale_m); /* Find smallest and biggest allowed vt divisor. */ dev_dbg(dev, "min_vt_div: %u\n", min_vt_div); @@ -420,6 +420,18 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, pll->op_lanes = 1; pll->vt_lanes = 1; } + + /* + * Make sure op_pix_clk_div will be integer --- unless flexible + * op_pix_clk_div is supported + */ + if (!(pll->flags & CCS_PLL_FLAG_FLEXIBLE_OP_PIX_CLK_DIV) && + (pll->bits_per_pixel * pll->op_lanes) % (pll->csi2.lanes * l)) { + dev_dbg(dev, "op_pix_clk_div not an integer (bpp %u, op lanes %u, lanes %u, l %u)\n", + pll->bits_per_pixel, pll->op_lanes, pll->csi2.lanes, l); + return -EINVAL; + } + dev_dbg(dev, "vt_lanes: %u\n", pll->vt_lanes); dev_dbg(dev, "op_lanes: %u\n", pll->op_lanes); @@ -449,9 +461,9 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, } pll->pixel_rate_csi = - op_pll_bk->pix_clk_freq_hz + op_pll_bk->sys_clk_freq_hz * (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ? - pll->csi2.lanes : 1) / l; + pll->csi2.lanes : 1) / pll->bits_per_pixel / l; /* Figure out limits for OP pre-pll divider based on extclk */ dev_dbg(dev, "min / max op_pre_pll_clk_div: %u / %u\n", diff --git a/drivers/media/i2c/ccs-pll.h b/drivers/media/i2c/ccs-pll.h index 207822cf2324..1b5c20736fe8 100644 --- a/drivers/media/i2c/ccs-pll.h +++ b/drivers/media/i2c/ccs-pll.h @@ -26,6 +26,7 @@ #define CCS_PLL_FLAG_LANE_SPEED_MODEL BIT(2) #define CCS_PLL_FLAG_LINK_DECOUPLED BIT(3) #define CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER BIT(4) +#define CCS_PLL_FLAG_FLEXIBLE_OP_PIX_CLK_DIV BIT(5) /** * struct ccs_pll_branch_fr - CCS PLL configuration (front) diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index d39da0f31d90..21158e6d0159 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -30,7 +30,6 @@ #include <media/v4l2-device.h> #include "ccs.h" -#include "ccs-limits.h" #define CCS_ALIGN_DIM(dim, flags) \ ((flags) & V4L2_SEL_FLAG_GE \ @@ -3222,6 +3221,9 @@ static int ccs_probe(struct i2c_client *client) if (CCS_LIM(sensor, CLOCK_TREE_PLL_CAPABILITY) & CCS_CLOCK_TREE_PLL_CAPABILITY_EXT_DIVIDER) sensor->pll.flags |= CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER; + if (CCS_LIM(sensor, CLOCK_TREE_PLL_CAPABILITY) & + CCS_CLOCK_TREE_PLL_CAPABILITY_FLEXIBLE_OP_PIX_CLK_DIV) + sensor->pll.flags |= CCS_PLL_FLAG_FLEXIBLE_OP_PIX_CLK_DIV; sensor->pll.op_bits_per_lane = CCS_LIM(sensor, OP_BITS_PER_LANE); sensor->pll.ext_clk_freq_hz = sensor->hwcfg.ext_clk; sensor->pll.scale_n = CCS_LIM(sensor, SCALER_N_MIN); |