OSDN Git Service

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 9750b49..cb19a36 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 fe8eb3d..fe20af1 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 a0d73e0..855e516 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 4fe8c6f..e3d4c7a 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;
 }