Commit 38c94eb8 authored by Sakari Ailus's avatar Sakari Ailus Committed by Mauro Carvalho Chehab
Browse files

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: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent 3e2db036
Loading
Loading
Loading
Loading
+55 −29
Original line number Diff line number Diff line
@@ -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);
+2 −0
Original line number Diff line number Diff line
@@ -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)
+7 −0
Original line number Diff line number Diff line
@@ -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);