media: ccs-pll: Add support for decoupled OP domain calculation
authorSakari Ailus <sakari.ailus@linux.intel.com>
Thu, 18 Jun 2020 10:39:44 +0000 (12:39 +0200)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Mon, 7 Dec 2020 14:53:34 +0000 (15:53 +0100)
Add support for decoupled OP domain clock calculation. This means that the
number of VT and OP domain clocks are no longer dependent on the number of
CSI-2 lanes in the lane speed mode.

The support also replaces the existing quirk flag to calculate OP domain
clocks per lane.

Also support decoupled OP domain calculation in the CCS driver.

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
drivers/media/i2c/ccs/ccs-quirk.c

index 9750b49d834a01ab82d222878d1e5e9e69f74b5d..cb19a36e54df5b6851b466d0e0dbd3671f88ae0f 100644 (file)
@@ -162,7 +162,7 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim,
                    const struct ccs_pll_branch_limits_bk *op_lim_bk,
                    struct ccs_pll *pll, struct ccs_pll_branch_fr *op_pll_fr,
                    struct ccs_pll_branch_bk *op_pll_bk, uint32_t mul,
-                   uint32_t div, uint32_t lane_op_clock_ratio)
+                   uint32_t div)
 {
        uint32_t sys_div;
        uint32_t best_pix_div = INT_MAX >> 1;
@@ -194,7 +194,8 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim,
                min_t(uint32_t,
                      more_mul_max,
                      op_lim_fr->max_pll_op_clk_freq_hz
-                     / (pll->ext_clk_freq_hz / op_pll_fr->pre_pll_clk_div * mul));
+                     / (pll->ext_clk_freq_hz /
+                        op_pll_fr->pre_pll_clk_div * mul));
        dev_dbg(dev, "more_mul_max: max_pll_op_clk_freq_hz check: %u\n",
                more_mul_max);
        /* Don't go above the division capability of op sys clock divider. */
@@ -257,7 +258,6 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim,
                op_pll_bk->sys_clk_freq_hz / op_pll_bk->pix_clk_div;
        dev_dbg(dev, "op_pix_clk_div: %u\n", op_pll_bk->pix_clk_div);
 
-
        if (pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) {
                /* No OP clocks --- VT clocks are used instead. */
                goto out_skip_vt_calc;
@@ -293,7 +293,7 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim,
                                  * op_pll_bk->sys_clk_div * pll->scale_n
                                  * pll->vt_lanes,
                                  pll->op_lanes * vt_op_binning_div
-                                 * pll->scale_m * lane_op_clock_ratio);
+                                 * pll->scale_m);
 
        /* Find smallest and biggest allowed vt divisor. */
        dev_dbg(dev, "min_vt_div: %u\n", min_vt_div);
@@ -405,7 +405,6 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim,
        struct ccs_pll_branch_bk *op_pll_bk = &pll->op_bk;
        uint16_t min_op_pre_pll_clk_div;
        uint16_t max_op_pre_pll_clk_div;
-       uint32_t lane_op_clock_ratio;
        uint32_t mul, div;
        uint32_t i;
        int rval = -EINVAL;
@@ -428,12 +427,6 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim,
                op_pll_bk = &pll->vt_bk;
        }
 
-       if (pll->flags & CCS_PLL_FLAG_OP_PIX_CLOCK_PER_LANE)
-               lane_op_clock_ratio = pll->csi2.lanes;
-       else
-               lane_op_clock_ratio = 1;
-       dev_dbg(dev, "lane_op_clock_ratio: %u\n", lane_op_clock_ratio);
-
        dev_dbg(dev, "binning: %ux%u\n", pll->binning_horizontal,
                pll->binning_vertical);
 
@@ -442,7 +435,7 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim,
                /* CSI transfers 2 bits per clock per lane; thus times 2 */
                op_pll_bk->sys_clk_freq_hz = pll->link_freq * 2
                        * (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ?
-                          1 : pll->csi2.lanes) / lane_op_clock_ratio;
+                          1 : pll->csi2.lanes);
                break;
        default:
                return -EINVAL;
@@ -451,7 +444,7 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim,
        pll->pixel_rate_csi =
                op_pll_bk->pix_clk_freq_hz
                * (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ?
-                  pll->csi2.lanes : 1) * lane_op_clock_ratio;
+                  pll->csi2.lanes : 1);
 
        /* Figure out limits for OP pre-pll divider based on extclk */
        dev_dbg(dev, "min / max op_pre_pll_clk_div: %u / %u\n",
@@ -487,8 +480,7 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim,
             op_pll_fr->pre_pll_clk_div <= max_op_pre_pll_clk_div;
             op_pll_fr->pre_pll_clk_div += 2 - (op_pll_fr->pre_pll_clk_div & 1)) {
                rval = __ccs_pll_calculate(dev, lim, op_lim_fr, op_lim_bk, pll,
-                                          op_pll_fr, op_pll_bk, mul, div,
-                                          lane_op_clock_ratio);
+                                          op_pll_fr, op_pll_bk, mul, div);
                if (rval)
                        continue;
 
index fe8eb3d4bcffd745ef6c1f5e548c725d004df9e5..fe20af11a068d8dfa834a54170012c08e4acfa02 100644 (file)
@@ -24,6 +24,7 @@
 #define CCS_PLL_FLAG_NO_OP_CLOCKS                              BIT(1)
 /* CCS PLL flags */
 #define CCS_PLL_FLAG_LANE_SPEED_MODEL                          BIT(2)
+#define CCS_PLL_FLAG_LINK_DECOUPLED                            BIT(3)
 
 /**
  * struct ccs_pll_branch_fr - CCS PLL configuration (front)
index a0d73e0fa31abe397ac4b084828406592fc0a7ab..855e51675864d049c24696c8c32e347bebdcaae7 100644 (file)
@@ -3206,10 +3206,18 @@ static int ccs_probe(struct i2c_client *client)
        sensor->pll.csi2.lanes = sensor->hwcfg.lanes;
        if (CCS_LIM(sensor, CLOCK_CALCULATION) &
            CCS_CLOCK_CALCULATION_LANE_SPEED) {
-               sensor->pll.vt_lanes =
-                       CCS_LIM(sensor, NUM_OF_VT_LANES) + 1;
-               sensor->pll.op_lanes = sensor->pll.vt_lanes;
                sensor->pll.flags |= CCS_PLL_FLAG_LANE_SPEED_MODEL;
+               if (CCS_LIM(sensor, CLOCK_CALCULATION) &
+                   CCS_CLOCK_CALCULATION_LINK_DECOUPLED) {
+                       sensor->pll.vt_lanes =
+                               CCS_LIM(sensor, NUM_OF_VT_LANES) + 1;
+                       sensor->pll.op_lanes =
+                               CCS_LIM(sensor, NUM_OF_OP_LANES) + 1;
+                       sensor->pll.flags |= CCS_PLL_FLAG_LINK_DECOUPLED;
+               } else {
+                       sensor->pll.vt_lanes = sensor->pll.csi2.lanes;
+                       sensor->pll.op_lanes = sensor->pll.csi2.lanes;
+               }
        }
        sensor->pll.ext_clk_freq_hz = sensor->hwcfg.ext_clk;
        sensor->pll.scale_n = CCS_LIM(sensor, SCALER_N_MIN);
index 4fe8c6f70579fe8dd83703567bc8a86cab0aa2ed..e3d4c7a275bc84f92c882979b17e9035e427dae6 100644 (file)
@@ -190,7 +190,10 @@ static int jt8ev1_post_streamoff(struct ccs_sensor *sensor)
 
 static int jt8ev1_init(struct ccs_sensor *sensor)
 {
-       sensor->pll.flags |= CCS_PLL_FLAG_OP_PIX_CLOCK_PER_LANE;
+       sensor->pll.flags |= CCS_PLL_FLAG_LANE_SPEED_MODEL |
+               CCS_PLL_FLAG_LINK_DECOUPLED;
+       sensor->pll.vt_lanes = 1;
+       sensor->pll.op_lanes = sensor->pll.csi2.lanes;
 
        return 0;
 }