media: ccs-pll: Check for derating and overrating, support non-derating sensors
authorSakari Ailus <sakari.ailus@linux.intel.com>
Fri, 28 Aug 2020 06:24:18 +0000 (08:24 +0200)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Mon, 7 Dec 2020 14:59:59 +0000 (15:59 +0100)
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>
drivers/media/i2c/ccs-pll.c
drivers/media/i2c/ccs-pll.h
drivers/media/i2c/ccs/ccs-core.c

index 3d43e737155ff5bacd12e32f11b0a3f640f60b94..96eb71f16c813acbc49d43250f2fb54a850505bd 100644 (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;
 }
 
@@ -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;
 
        /*
-        * 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.
+        * 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 (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);
+       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
+                * 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]
-        *
-        * Horizontal binning can be used as a base for difference in
-        * divisors. One must make sure that horizontal blanking is
-        * enough to accommodate the CSI-2 sync codes.
-        *
-        * Take scaling factor and number of VT lanes into account as well.
-        *
-        * 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 ?
-                                  pll->csi2.lanes : 1)
-                                 * vt_op_binning_div * pll->scale_m
-                                 * PHY_CONST_DIV);
+               /*
+                * Profile 2 supports vt_pix_clk_div E [4, 10]
+                *
+                * Horizontal binning can be used as a base for difference in
+                * divisors. One must make sure that horizontal blanking is
+                * enough to accommodate the CSI-2 sync codes.
+                *
+                * Take scaling factor and number of VT lanes into account as well.
+                *
+                * 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 ?
+                                     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);
index 1b5c20736fe89b78b3309ceada61e98b295ef0ff..03c2428c76cdfb927ce7f98003a72c8c443a5e13 100644 (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)
index 21158e6d0159967aee90110315d5b8f75a6aa4c4..fa878ecf55a7b6d237c02f37ba40d2dcae811fa7 100644 (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);