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,
"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;
}
@ -162,6 +174,16 @@ __ccs_pll_calculate_vt(struct device *dev, const struct ccs_pll_limits *lim,
uint32_t min_vt_div, max_vt_div, vt_div;
uint32_t min_sys_div, max_sys_div;
/*
* 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;
} else {
/*
* Some sensors perform analogue binning and some do this
* digitally. The ones doing this digitally can be roughly be
@ -188,12 +210,16 @@ __ccs_pll_calculate_vt(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(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 ?
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);
}
/* Find smallest and biggest allowed vt divisor. */
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_EXT_IP_PLL_DIVIDER BIT(4)
#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)

View File

@ -3224,6 +3224,13 @@ static int ccs_probe(struct i2c_client *client)
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;
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.ext_clk_freq_hz = sensor->hwcfg.ext_clk;
sensor->pll.scale_n = CCS_LIM(sensor, SCALER_N_MIN);