[media] smiapp-pll: Calculate OP clocks only for sensors that have them
authorSakari Ailus <sakari.ailus@linux.intel.com>
Tue, 16 Sep 2014 12:39:08 +0000 (09:39 -0300)
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>
Tue, 28 Oct 2014 15:36:56 +0000 (13:36 -0200)
Profile 0 sensors have no OP clock branck in the clock tree. The PLL
calculator still calculated them, they just weren't used for anything.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
drivers/media/i2c/smiapp-pll.c

index 40a18ba8555711b24f60e6956b32b925f30577e4..cac1407b77fb01ba4d16265fd3d638f520599e03 100644 (file)
@@ -89,7 +89,9 @@ static void print_pll(struct device *dev, struct smiapp_pll *pll)
 
 static int check_all_bounds(struct device *dev,
                            const struct smiapp_pll_limits *limits,
-                           struct smiapp_pll *pll)
+                           const struct smiapp_pll_branch_limits *op_limits,
+                           struct smiapp_pll *pll,
+                           struct smiapp_pll_branch *op_pll)
 {
        int rval;
 
@@ -109,25 +111,25 @@ static int check_all_bounds(struct device *dev,
                        "pll_op_clk_freq_hz");
        if (!rval)
                rval = bounds_check(
-                       dev, pll->op.sys_clk_div,
-                       limits->op.min_sys_clk_div, limits->op.max_sys_clk_div,
+                       dev, op_pll->sys_clk_div,
+                       op_limits->min_sys_clk_div, op_limits->max_sys_clk_div,
                        "op_sys_clk_div");
        if (!rval)
                rval = bounds_check(
-                       dev, pll->op.pix_clk_div,
-                       limits->op.min_pix_clk_div, limits->op.max_pix_clk_div,
+                       dev, op_pll->pix_clk_div,
+                       op_limits->min_pix_clk_div, op_limits->max_pix_clk_div,
                        "op_pix_clk_div");
        if (!rval)
                rval = bounds_check(
-                       dev, pll->op.sys_clk_freq_hz,
-                       limits->op.min_sys_clk_freq_hz,
-                       limits->op.max_sys_clk_freq_hz,
+                       dev, op_pll->sys_clk_freq_hz,
+                       op_limits->min_sys_clk_freq_hz,
+                       op_limits->max_sys_clk_freq_hz,
                        "op_sys_clk_freq_hz");
        if (!rval)
                rval = bounds_check(
-                       dev, pll->op.pix_clk_freq_hz,
-                       limits->op.min_pix_clk_freq_hz,
-                       limits->op.max_pix_clk_freq_hz,
+                       dev, op_pll->pix_clk_freq_hz,
+                       op_limits->min_pix_clk_freq_hz,
+                       op_limits->max_pix_clk_freq_hz,
                        "op_pix_clk_freq_hz");
        if (!rval)
                rval = bounds_check(
@@ -156,10 +158,11 @@ static int check_all_bounds(struct device *dev,
  *
  * @return Zero on success, error code on error.
  */
-static int __smiapp_pll_calculate(struct device *dev,
-                                 const struct smiapp_pll_limits *limits,
-                                 struct smiapp_pll *pll, uint32_t mul,
-                                 uint32_t div, uint32_t lane_op_clock_ratio)
+static int __smiapp_pll_calculate(
+       struct device *dev, const struct smiapp_pll_limits *limits,
+       const struct smiapp_pll_branch_limits *op_limits,
+       struct smiapp_pll *pll, struct smiapp_pll_branch *op_pll, uint32_t mul,
+       uint32_t div, uint32_t lane_op_clock_ratio)
 {
        uint32_t sys_div;
        uint32_t best_pix_div = INT_MAX >> 1;
@@ -196,7 +199,7 @@ static int __smiapp_pll_calculate(struct device *dev,
                more_mul_max);
        /* Don't go above the division capability of op sys clock divider. */
        more_mul_max = min(more_mul_max,
-                          limits->op.max_sys_clk_div * pll->pre_pll_clk_div
+                          op_limits->max_sys_clk_div * pll->pre_pll_clk_div
                           / div);
        dev_dbg(dev, "more_mul_max: max_op_sys_clk_div check: %u\n",
                more_mul_max);
@@ -226,8 +229,8 @@ static int __smiapp_pll_calculate(struct device *dev,
 
        more_mul_factor = lcm(div, pll->pre_pll_clk_div) / div;
        dev_dbg(dev, "more_mul_factor: %u\n", more_mul_factor);
-       more_mul_factor = lcm(more_mul_factor, limits->op.min_sys_clk_div);
-       dev_dbg(dev, "more_mul_factor: min_op_sys_clk_div: %u\n",
+       more_mul_factor = lcm(more_mul_factor, op_limits->min_sys_clk_div);
+       dev_dbg(dev, "more_mul_factor: min_op_sys_clk_div: %d\n",
                more_mul_factor);
        i = roundup(more_mul_min, more_mul_factor);
        if (!is_one_or_even(i))
@@ -240,8 +243,8 @@ static int __smiapp_pll_calculate(struct device *dev,
        }
 
        pll->pll_multiplier = mul * i;
-       pll->op.sys_clk_div = div * i / pll->pre_pll_clk_div;
-       dev_dbg(dev, "op_sys_clk_div: %u\n", pll->op.sys_clk_div);
+       op_pll->sys_clk_div = div * i / pll->pre_pll_clk_div;
+       dev_dbg(dev, "op_sys_clk_div: %u\n", op_pll->sys_clk_div);
 
        pll->pll_ip_clk_freq_hz = pll->ext_clk_freq_hz
                / pll->pre_pll_clk_div;
@@ -250,14 +253,19 @@ static int __smiapp_pll_calculate(struct device *dev,
                * pll->pll_multiplier;
 
        /* Derive pll_op_clk_freq_hz. */
-       pll->op.sys_clk_freq_hz =
-               pll->pll_op_clk_freq_hz / pll->op.sys_clk_div;
+       op_pll->sys_clk_freq_hz =
+               pll->pll_op_clk_freq_hz / op_pll->sys_clk_div;
 
-       pll->op.pix_clk_div = pll->bits_per_pixel;
-       dev_dbg(dev, "op_pix_clk_div: %u\n", pll->op.pix_clk_div);
+       op_pll->pix_clk_div = pll->bits_per_pixel;
+       dev_dbg(dev, "op_pix_clk_div: %u\n", op_pll->pix_clk_div);
 
-       pll->op.pix_clk_freq_hz =
-               pll->op.sys_clk_freq_hz / pll->op.pix_clk_div;
+       op_pll->pix_clk_freq_hz =
+               op_pll->sys_clk_freq_hz / op_pll->pix_clk_div;
+
+       if (pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS) {
+               /* No OP clocks --- VT clocks are used instead. */
+               goto out_skip_vt_calc;
+       }
 
        /*
         * Some sensors perform analogue binning and some do this
@@ -285,7 +293,7 @@ static int __smiapp_pll_calculate(struct device *dev,
         * 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->op.pix_clk_div * pll->op.sys_clk_div
+       min_vt_div = DIV_ROUND_UP(op_pll->pix_clk_div * op_pll->sys_clk_div
                                  * pll->scale_n,
                                  lane_op_clock_ratio * vt_op_binning_div
                                  * pll->scale_m);
@@ -377,16 +385,19 @@ static int __smiapp_pll_calculate(struct device *dev,
        pll->vt.pix_clk_freq_hz =
                pll->vt.sys_clk_freq_hz / pll->vt.pix_clk_div;
 
+out_skip_vt_calc:
        pll->pixel_rate_csi =
-               pll->op.pix_clk_freq_hz * lane_op_clock_ratio;
+               op_pll->pix_clk_freq_hz * lane_op_clock_ratio;
 
-       return check_all_bounds(dev, limits, pll);
+       return check_all_bounds(dev, limits, op_limits, pll, op_pll);
 }
 
 int smiapp_pll_calculate(struct device *dev,
                         const struct smiapp_pll_limits *limits,
                         struct smiapp_pll *pll)
 {
+       const struct smiapp_pll_branch_limits *op_limits = &limits->op;
+       struct smiapp_pll_branch *op_pll = &pll->op;
        uint16_t min_pre_pll_clk_div;
        uint16_t max_pre_pll_clk_div;
        uint32_t lane_op_clock_ratio;
@@ -394,6 +405,16 @@ int smiapp_pll_calculate(struct device *dev,
        unsigned int i;
        int rval = -EINVAL;
 
+       if (pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS) {
+               /*
+                * If there's no OP PLL at all, use the VT values
+                * instead. The OP values are ignored for the rest of
+                * the PLL calculation.
+                */
+               op_limits = &limits->vt;
+               op_pll = &pll->vt;
+       }
+
        if (pll->flags & SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE)
                lane_op_clock_ratio = pll->csi2.lanes;
        else
@@ -449,7 +470,8 @@ int smiapp_pll_calculate(struct device *dev,
        for (pll->pre_pll_clk_div = min_pre_pll_clk_div;
             pll->pre_pll_clk_div <= max_pre_pll_clk_div;
             pll->pre_pll_clk_div += 2 - (pll->pre_pll_clk_div & 1)) {
-               rval = __smiapp_pll_calculate(dev, limits, pll, mul, div,
+               rval = __smiapp_pll_calculate(dev, limits, op_limits, pll,
+                                             op_pll, mul, div,
                                              lane_op_clock_ratio);
                if (rval)
                        continue;