summaryrefslogtreecommitdiff
path: root/drivers/media
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/i2c/ccs-pll.c26
-rw-r--r--drivers/media/i2c/ccs-pll.h1
-rw-r--r--drivers/media/i2c/ccs/ccs-core.c4
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);