media: ccs-pll: Check for derating and overrating, support non-derating sensors

Some sensors support derating (VT domain speed faster than OP) or
overrating (VT domain speed slower than OP). While this was supported for
the driver, the hardware support for the feature was never verified. Do
that now, and for those devices without that support, VT and OP speeds
have to match.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
This commit is contained in:
Sakari Ailus 2020-08-28 08:24:18 +02:00 committed by Mauro Carvalho Chehab
parent 3e2db036c9
commit 38c94eb8d7
3 changed files with 64 additions and 29 deletions

View File

@ -142,6 +142,18 @@ static int check_all_bounds(struct device *dev,
lim->vt_bk.max_pix_clk_freq_hz, lim->vt_bk.max_pix_clk_freq_hz,
"vt_pix_clk_freq_hz"); "vt_pix_clk_freq_hz");
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 rval; return rval;
} }
@ -163,37 +175,51 @@ __ccs_pll_calculate_vt(struct device *dev, const struct ccs_pll_limits *lim,
uint32_t min_sys_div, max_sys_div; uint32_t min_sys_div, max_sys_div;
/* /*
* Some sensors perform analogue binning and some do this * Find out whether a sensor supports derating. If it does not, VT and
* digitally. The ones doing this digitally can be roughly be * OP domains are required to run at the same pixel rate.
* 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 if (!(pll->flags & CCS_PLL_FLAG_FIFO_DERATING)) {
/ pll->binning_horizontal) min_vt_div =
vt_op_binning_div = pll->binning_horizontal; op_pll_bk->sys_clk_div * op_pll_bk->pix_clk_div
else * pll->vt_lanes * phy_const
vt_op_binning_div = 1; / pll->op_lanes / PHY_CONST_DIV;
dev_dbg(dev, "vt_op_binning_div: %u\n", vt_op_binning_div); } 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] * Profile 2 supports vt_pix_clk_div E [4, 10]
* *
* Horizontal binning can be used as a base for difference in * Horizontal binning can be used as a base for difference in
* divisors. One must make sure that horizontal blanking is * divisors. One must make sure that horizontal blanking is
* enough to accommodate the CSI-2 sync codes. * enough to accommodate the CSI-2 sync codes.
* *
* Take scaling factor and number of VT lanes into account as well. * Take scaling factor and number of VT lanes into account as well.
* *
* Find absolute limits for the factor of vt divider. * Find absolute limits for the factor of vt divider.
*/ */
dev_dbg(dev, "scale_m: %u\n", pll->scale_m); 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 min_vt_div =
* pll->scale_n * pll->vt_lanes * phy_const, DIV_ROUND_UP(pll->bits_per_pixel
(pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ? * op_pll_bk->sys_clk_div * pll->scale_n
pll->csi2.lanes : 1) * pll->vt_lanes * phy_const,
* vt_op_binning_div * pll->scale_m (pll->flags &
* PHY_CONST_DIV); CCS_PLL_FLAG_LANE_SPEED_MODEL ?
pll->csi2.lanes : 1)
* vt_op_binning_div * pll->scale_m
* PHY_CONST_DIV);
}
/* Find smallest and biggest allowed vt divisor. */ /* Find smallest and biggest allowed vt divisor. */
dev_dbg(dev, "min_vt_div: %u\n", min_vt_div); dev_dbg(dev, "min_vt_div: %u\n", min_vt_div);

View File

@ -27,6 +27,8 @@
#define CCS_PLL_FLAG_LINK_DECOUPLED BIT(3) #define CCS_PLL_FLAG_LINK_DECOUPLED BIT(3)
#define CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER BIT(4) #define CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER BIT(4)
#define CCS_PLL_FLAG_FLEXIBLE_OP_PIX_CLK_DIV BIT(5) #define CCS_PLL_FLAG_FLEXIBLE_OP_PIX_CLK_DIV BIT(5)
#define CCS_PLL_FLAG_FIFO_DERATING BIT(6)
#define CCS_PLL_FLAG_FIFO_OVERRATING BIT(7)
/** /**
* struct ccs_pll_branch_fr - CCS PLL configuration (front) * struct ccs_pll_branch_fr - CCS PLL configuration (front)

View File

@ -3224,6 +3224,13 @@ static int ccs_probe(struct i2c_client *client)
if (CCS_LIM(sensor, CLOCK_TREE_PLL_CAPABILITY) & if (CCS_LIM(sensor, CLOCK_TREE_PLL_CAPABILITY) &
CCS_CLOCK_TREE_PLL_CAPABILITY_FLEXIBLE_OP_PIX_CLK_DIV) CCS_CLOCK_TREE_PLL_CAPABILITY_FLEXIBLE_OP_PIX_CLK_DIV)
sensor->pll.flags |= CCS_PLL_FLAG_FLEXIBLE_OP_PIX_CLK_DIV; sensor->pll.flags |= CCS_PLL_FLAG_FLEXIBLE_OP_PIX_CLK_DIV;
if (CCS_LIM(sensor, FIFO_SUPPORT_CAPABILITY) &
CCS_FIFO_SUPPORT_CAPABILITY_DERATING)
sensor->pll.flags |= CCS_PLL_FLAG_FIFO_DERATING;
if (CCS_LIM(sensor, FIFO_SUPPORT_CAPABILITY) &
CCS_FIFO_SUPPORT_CAPABILITY_DERATING_OVERRATING)
sensor->pll.flags |= CCS_PLL_FLAG_FIFO_DERATING |
CCS_PLL_FLAG_FIFO_OVERRATING;
sensor->pll.op_bits_per_lane = CCS_LIM(sensor, OP_BITS_PER_LANE); 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.ext_clk_freq_hz = sensor->hwcfg.ext_clk;
sensor->pll.scale_n = CCS_LIM(sensor, SCALER_N_MIN); sensor->pll.scale_n = CCS_LIM(sensor, SCALER_N_MIN);