OSDN Git Service

media: ccs-pll: Add support for lane speed model
authorSakari Ailus <sakari.ailus@linux.intel.com>
Mon, 22 Jun 2020 10:16:24 +0000 (12:16 +0200)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Mon, 7 Dec 2020 14:52:09 +0000 (15:52 +0100)
CCS PLL includes a capability to calculate the VT clocks on per-lane
basis. Add support for this feature.

Move calculation of the pixel rate on the CSI-2 bus early in the function
as everything needed to calculate it is already available.

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

index d33a257..9750b49 100644 (file)
@@ -251,11 +251,12 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim,
        op_pll_fr->pll_op_clk_freq_hz = op_pll_fr->pll_ip_clk_freq_hz
                * op_pll_fr->pll_multiplier;
 
-       op_pll_bk->pix_clk_div = pll->bits_per_pixel;
-       dev_dbg(dev, "op_pix_clk_div: %u\n", op_pll_bk->pix_clk_div);
-
+       op_pll_bk->pix_clk_div = pll->bits_per_pixel
+               * pll->op_lanes / pll->csi2.lanes;
        op_pll_bk->pix_clk_freq_hz =
                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. */
@@ -283,15 +284,16 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim,
         * divisors. One must make sure that horizontal blanking is
         * enough to accommodate the CSI-2 sync codes.
         *
-        * Take scaling factor into account as well.
+        * 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(op_pll_bk->pix_clk_div
-                                 * op_pll_bk->sys_clk_div * pll->scale_n,
-                                 lane_op_clock_ratio * vt_op_binning_div
-                                 * pll->scale_m);
+                                 * 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);
 
        /* Find smallest and biggest allowed vt divisor. */
        dev_dbg(dev, "min_vt_div: %u\n", min_vt_div);
@@ -387,9 +389,8 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim,
                pll->vt_bk.sys_clk_freq_hz / pll->vt_bk.pix_clk_div;
 
 out_skip_vt_calc:
-       pll->pixel_rate_csi =
-               op_pll_bk->pix_clk_freq_hz * lane_op_clock_ratio;
-       pll->pixel_rate_pixel_array = pll->vt_bk.pix_clk_freq_hz;
+       pll->pixel_rate_pixel_array =
+               pll->vt_bk.pix_clk_freq_hz * pll->vt_lanes;
 
        return check_all_bounds(dev, lim, op_lim_fr, op_lim_bk, pll, op_pll_fr,
                                op_pll_bk);
@@ -409,6 +410,13 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim,
        uint32_t i;
        int rval = -EINVAL;
 
+       if (!(pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL)) {
+               pll->op_lanes = 1;
+               pll->vt_lanes = 1;
+       }
+       dev_dbg(dev, "vt_lanes: %u\n", pll->vt_lanes);
+       dev_dbg(dev, "op_lanes: %u\n", pll->op_lanes);
+
        if (pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) {
                /*
                 * If there's no OP PLL at all, use the VT values
@@ -433,12 +441,18 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim,
        case CCS_PLL_BUS_TYPE_CSI2_DPHY:
                /* CSI transfers 2 bits per clock per lane; thus times 2 */
                op_pll_bk->sys_clk_freq_hz = pll->link_freq * 2
-                       * (pll->csi2.lanes / lane_op_clock_ratio);
+                       * (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ?
+                          1 : pll->csi2.lanes) / lane_op_clock_ratio;
                break;
        default:
                return -EINVAL;
        }
 
+       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;
+
        /* Figure out limits for OP pre-pll divider based on extclk */
        dev_dbg(dev, "min / max op_pre_pll_clk_div: %u / %u\n",
                op_lim_fr->min_pre_pll_clk_div, op_lim_fr->max_pre_pll_clk_div);
index 3ad4e65..fe8eb3d 100644 (file)
@@ -22,6 +22,8 @@
 /* op pix clock is for all lanes in total normally */
 #define CCS_PLL_FLAG_OP_PIX_CLOCK_PER_LANE                     BIT(0)
 #define CCS_PLL_FLAG_NO_OP_CLOCKS                              BIT(1)
+/* CCS PLL flags */
+#define CCS_PLL_FLAG_LANE_SPEED_MODEL                          BIT(2)
 
 /**
  * struct ccs_pll_branch_fr - CCS PLL configuration (front)
@@ -63,6 +65,8 @@ struct ccs_pll_branch_bk {
  * All information required to calculate CCS PLL configuration.
  *
  * @bus_type: Type of the data bus, CCS_PLL_BUS_TYPE_* (input)
+ * @op_lanes: Number of operational lanes (input)
+ * @vt_lanes: Number of video timing lanes (input)
  * @csi2: CSI-2 related parameters
  * @csi2.lanes: The number of the CSI-2 data lanes (input)
  * @binning_vertical: Vertical binning factor (input)
@@ -84,6 +88,8 @@ struct ccs_pll_branch_bk {
 struct ccs_pll {
        /* input values */
        uint8_t bus_type;
+       uint8_t op_lanes;
+       uint8_t vt_lanes;
        struct {
                uint8_t lanes;
        } csi2;