From patchwork Wed Dec 2 18:06:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946577 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2D335C64E7B for ; Wed, 2 Dec 2020 18:11:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CF91722240 for ; Wed, 2 Dec 2020 18:11:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728935AbgLBSLY (ORCPT ); Wed, 2 Dec 2020 13:11:24 -0500 Received: from retiisi.eu ([95.216.213.190]:33472 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728677AbgLBSLX (ORCPT ); Wed, 2 Dec 2020 13:11:23 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id E41FA634C87; Wed, 2 Dec 2020 20:08:30 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 01/38] ccs-pll: Don't use div_u64 to divide a 32-bit number Date: Wed, 2 Dec 2020 20:06:04 +0200 Message-Id: <20201202180641.17401-2-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org pll->pll_op_clk_freq is a 32-bit number. It does not need div_u64 to divide it. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index 0d57bac1599a..1cfe6cf7e51c 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -445,7 +445,7 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *limits, min_pre_pll_clk_div, max_pre_pll_clk_div); i = gcd(pll->pll_op_clk_freq_hz, pll->ext_clk_freq_hz); - mul = div_u64(pll->pll_op_clk_freq_hz, i); + mul = pll->pll_op_clk_freq_hz / i; div = pll->ext_clk_freq_hz / i; dev_dbg(dev, "mul %u / div %u\n", mul, div); From patchwork Wed Dec 2 18:06:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946595 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 06882C83016 for ; Wed, 2 Dec 2020 18:11:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 96199221FC for ; Wed, 2 Dec 2020 18:11:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387548AbgLBSL1 (ORCPT ); Wed, 2 Dec 2020 13:11:27 -0500 Received: from retiisi.eu ([95.216.213.190]:33476 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728900AbgLBSL1 (ORCPT ); Wed, 2 Dec 2020 13:11:27 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 0093B634C89; Wed, 2 Dec 2020 20:08:31 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 02/38] ccs-pll: Split limits and PLL configuration into front and back parts Date: Wed, 2 Dec 2020 20:06:05 +0200 Message-Id: <20201202180641.17401-3-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The CCS spec supports a lot of variation in the PLL. Split the PLL in front and back parts to better prepare for supporting it. Also use CCS compliant naming for IP and OP PLL frequencies (i.e. include "clk" in the name). Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 282 ++++++++++++++++--------------- drivers/media/i2c/ccs-pll.h | 44 +++-- drivers/media/i2c/ccs/ccs-core.c | 71 ++++---- 3 files changed, 209 insertions(+), 188 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index 1cfe6cf7e51c..b2f0fa14ff92 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -53,65 +53,68 @@ static int bounds_check(struct device *dev, uint32_t val, static void print_pll(struct device *dev, struct ccs_pll *pll) { - dev_dbg(dev, "pre_pll_clk_div\t%u\n", pll->pre_pll_clk_div); - dev_dbg(dev, "pll_multiplier \t%u\n", pll->pll_multiplier); + dev_dbg(dev, "pre_pll_clk_div\t%u\n", pll->vt_fr.pre_pll_clk_div); + dev_dbg(dev, "pll_multiplier \t%u\n", pll->vt_fr.pll_multiplier); if (!(pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS)) { - dev_dbg(dev, "op_sys_clk_div \t%u\n", pll->op.sys_clk_div); - dev_dbg(dev, "op_pix_clk_div \t%u\n", pll->op.pix_clk_div); + dev_dbg(dev, "op_sys_clk_div \t%u\n", pll->op_bk.sys_clk_div); + dev_dbg(dev, "op_pix_clk_div \t%u\n", pll->op_bk.pix_clk_div); } - dev_dbg(dev, "vt_sys_clk_div \t%u\n", pll->vt.sys_clk_div); - dev_dbg(dev, "vt_pix_clk_div \t%u\n", pll->vt.pix_clk_div); + dev_dbg(dev, "vt_sys_clk_div \t%u\n", pll->vt_bk.sys_clk_div); + dev_dbg(dev, "vt_pix_clk_div \t%u\n", pll->vt_bk.pix_clk_div); dev_dbg(dev, "ext_clk_freq_hz \t%u\n", pll->ext_clk_freq_hz); - dev_dbg(dev, "pll_ip_clk_freq_hz \t%u\n", pll->pll_ip_clk_freq_hz); - dev_dbg(dev, "pll_op_clk_freq_hz \t%u\n", pll->pll_op_clk_freq_hz); + dev_dbg(dev, "pll_ip_clk_freq_hz \t%u\n", pll->vt_fr.pll_ip_clk_freq_hz); + dev_dbg(dev, "pll_op_clk_freq_hz \t%u\n", pll->vt_fr.pll_op_clk_freq_hz); if (!(pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS)) { dev_dbg(dev, "op_sys_clk_freq_hz \t%u\n", - pll->op.sys_clk_freq_hz); + pll->op_bk.sys_clk_freq_hz); dev_dbg(dev, "op_pix_clk_freq_hz \t%u\n", - pll->op.pix_clk_freq_hz); + pll->op_bk.pix_clk_freq_hz); } - dev_dbg(dev, "vt_sys_clk_freq_hz \t%u\n", pll->vt.sys_clk_freq_hz); - dev_dbg(dev, "vt_pix_clk_freq_hz \t%u\n", pll->vt.pix_clk_freq_hz); + dev_dbg(dev, "vt_sys_clk_freq_hz \t%u\n", pll->vt_bk.sys_clk_freq_hz); + dev_dbg(dev, "vt_pix_clk_freq_hz \t%u\n", pll->vt_bk.pix_clk_freq_hz); } static int check_all_bounds(struct device *dev, - const struct ccs_pll_limits *limits, - const struct ccs_pll_branch_limits *op_limits, - struct ccs_pll *pll, struct ccs_pll_branch *op_pll) + const struct ccs_pll_limits *lim, + const struct ccs_pll_branch_limits_fr *op_lim_fr, + 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) { int rval; - rval = bounds_check(dev, pll->pll_ip_clk_freq_hz, - limits->min_pll_ip_freq_hz, - limits->max_pll_ip_freq_hz, + rval = bounds_check(dev, op_pll_fr->pll_ip_clk_freq_hz, + op_lim_fr->min_pll_ip_clk_freq_hz, + op_lim_fr->max_pll_ip_clk_freq_hz, "pll_ip_clk_freq_hz"); if (!rval) rval = bounds_check( - dev, pll->pll_multiplier, - limits->min_pll_multiplier, limits->max_pll_multiplier, - "pll_multiplier"); + dev, op_pll_fr->pll_multiplier, + op_lim_fr->min_pll_multiplier, + op_lim_fr->max_pll_multiplier, "pll_multiplier"); if (!rval) rval = bounds_check( - dev, pll->pll_op_clk_freq_hz, - limits->min_pll_op_freq_hz, limits->max_pll_op_freq_hz, - "pll_op_clk_freq_hz"); + dev, op_pll_fr->pll_op_clk_freq_hz, + op_lim_fr->min_pll_op_clk_freq_hz, + op_lim_fr->max_pll_op_clk_freq_hz, "pll_op_clk_freq_hz"); if (!rval) rval = bounds_check( - dev, op_pll->sys_clk_div, - op_limits->min_sys_clk_div, op_limits->max_sys_clk_div, + dev, op_pll_bk->sys_clk_div, + op_lim_bk->min_sys_clk_div, op_lim_bk->max_sys_clk_div, "op_sys_clk_div"); if (!rval) rval = bounds_check( - dev, op_pll->sys_clk_freq_hz, - op_limits->min_sys_clk_freq_hz, - op_limits->max_sys_clk_freq_hz, + dev, op_pll_bk->sys_clk_freq_hz, + op_lim_bk->min_sys_clk_freq_hz, + op_lim_bk->max_sys_clk_freq_hz, "op_sys_clk_freq_hz"); if (!rval) rval = bounds_check( - dev, op_pll->pix_clk_freq_hz, - op_limits->min_pix_clk_freq_hz, - op_limits->max_pix_clk_freq_hz, + dev, op_pll_bk->pix_clk_freq_hz, + op_lim_bk->min_pix_clk_freq_hz, + op_lim_bk->max_pix_clk_freq_hz, "op_pix_clk_freq_hz"); /* @@ -123,15 +126,15 @@ static int check_all_bounds(struct device *dev, if (!rval) rval = bounds_check( - dev, pll->vt.sys_clk_freq_hz, - limits->vt.min_sys_clk_freq_hz, - limits->vt.max_sys_clk_freq_hz, + dev, pll->vt_bk.sys_clk_freq_hz, + lim->vt_bk.min_sys_clk_freq_hz, + lim->vt_bk.max_sys_clk_freq_hz, "vt_sys_clk_freq_hz"); if (!rval) rval = bounds_check( - dev, pll->vt.pix_clk_freq_hz, - limits->vt.min_pix_clk_freq_hz, - limits->vt.max_pix_clk_freq_hz, + dev, pll->vt_bk.pix_clk_freq_hz, + lim->vt_bk.min_pix_clk_freq_hz, + lim->vt_bk.max_pix_clk_freq_hz, "vt_pix_clk_freq_hz"); return rval; @@ -149,10 +152,12 @@ static int check_all_bounds(struct device *dev, * @return Zero on success, error code on error. */ static int -__ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *limits, - const struct ccs_pll_branch_limits *op_limits, - struct ccs_pll *pll, struct ccs_pll_branch *op_pll, - uint32_t mul, uint32_t div, uint32_t lane_op_clock_ratio) +__ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, + const struct ccs_pll_branch_limits_fr *op_lim_fr, + 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 sys_div; uint32_t best_pix_div = INT_MAX >> 1; @@ -173,42 +178,42 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *limits, * Get pre_pll_clk_div so that our pll_op_clk_freq_hz won't be * too high. */ - dev_dbg(dev, "pre_pll_clk_div %u\n", pll->pre_pll_clk_div); + dev_dbg(dev, "op_pre_pll_clk_div %u\n", op_pll_fr->pre_pll_clk_div); /* Don't go above max pll multiplier. */ - more_mul_max = limits->max_pll_multiplier / mul; - dev_dbg(dev, "more_mul_max: max_pll_multiplier check: %u\n", + more_mul_max = op_lim_fr->max_pll_multiplier / mul; + dev_dbg(dev, "more_mul_max: max_op_pll_multiplier check: %u\n", more_mul_max); /* Don't go above max pll op frequency. */ more_mul_max = min_t(uint32_t, more_mul_max, - limits->max_pll_op_freq_hz - / (pll->ext_clk_freq_hz / pll->pre_pll_clk_div * mul)); - dev_dbg(dev, "more_mul_max: max_pll_op_freq_hz check: %u\n", + op_lim_fr->max_pll_op_clk_freq_hz + / (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. */ more_mul_max = min(more_mul_max, - op_limits->max_sys_clk_div * pll->pre_pll_clk_div + op_lim_bk->max_sys_clk_div * op_pll_fr->pre_pll_clk_div / div); dev_dbg(dev, "more_mul_max: max_op_sys_clk_div check: %u\n", more_mul_max); /* Ensure we won't go above min_pll_multiplier. */ more_mul_max = min(more_mul_max, - DIV_ROUND_UP(limits->max_pll_multiplier, mul)); + DIV_ROUND_UP(op_lim_fr->max_pll_multiplier, mul)); dev_dbg(dev, "more_mul_max: min_pll_multiplier check: %u\n", more_mul_max); - /* Ensure we won't go below min_pll_op_freq_hz. */ - more_mul_min = DIV_ROUND_UP(limits->min_pll_op_freq_hz, - pll->ext_clk_freq_hz / pll->pre_pll_clk_div - * mul); - dev_dbg(dev, "more_mul_min: min_pll_op_freq_hz check: %u\n", + /* Ensure we won't go below min_pll_op_clk_freq_hz. */ + more_mul_min = DIV_ROUND_UP(op_lim_fr->min_pll_op_clk_freq_hz, + pll->ext_clk_freq_hz / + op_pll_fr->pre_pll_clk_div * mul); + dev_dbg(dev, "more_mul_min: min_op_pll_op_clk_freq_hz check: %u\n", more_mul_min); /* Ensure we won't go below min_pll_multiplier. */ more_mul_min = max(more_mul_min, - DIV_ROUND_UP(limits->min_pll_multiplier, mul)); - dev_dbg(dev, "more_mul_min: min_pll_multiplier check: %u\n", + DIV_ROUND_UP(op_lim_fr->min_pll_multiplier, mul)); + dev_dbg(dev, "more_mul_min: min_op_pll_multiplier check: %u\n", more_mul_min); if (more_mul_min > more_mul_max) { @@ -217,9 +222,9 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *limits, return -EINVAL; } - more_mul_factor = lcm(div, pll->pre_pll_clk_div) / div; + more_mul_factor = lcm(div, op_pll_fr->pre_pll_clk_div) / div; dev_dbg(dev, "more_mul_factor: %u\n", more_mul_factor); - more_mul_factor = lcm(more_mul_factor, op_limits->min_sys_clk_div); + more_mul_factor = lcm(more_mul_factor, op_lim_bk->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); @@ -232,25 +237,25 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *limits, return -EINVAL; } - pll->pll_multiplier = mul * i; - 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); + op_pll_fr->pll_multiplier = mul * i; + op_pll_bk->sys_clk_div = div * i / op_pll_fr->pre_pll_clk_div; + dev_dbg(dev, "op_sys_clk_div: %u\n", op_pll_bk->sys_clk_div); - pll->pll_ip_clk_freq_hz = pll->ext_clk_freq_hz - / pll->pre_pll_clk_div; + op_pll_fr->pll_ip_clk_freq_hz = pll->ext_clk_freq_hz + / op_pll_fr->pre_pll_clk_div; - pll->pll_op_clk_freq_hz = pll->pll_ip_clk_freq_hz - * pll->pll_multiplier; + op_pll_fr->pll_op_clk_freq_hz = op_pll_fr->pll_ip_clk_freq_hz + * op_pll_fr->pll_multiplier; /* Derive pll_op_clk_freq_hz. */ - op_pll->sys_clk_freq_hz = - pll->pll_op_clk_freq_hz / op_pll->sys_clk_div; + op_pll_bk->sys_clk_freq_hz = + op_pll_fr->pll_op_clk_freq_hz / op_pll_bk->sys_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); + 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->pix_clk_freq_hz = - op_pll->sys_clk_freq_hz / op_pll->pix_clk_div; + op_pll_bk->pix_clk_freq_hz = + op_pll_bk->sys_clk_freq_hz / op_pll_bk->pix_clk_div; if (pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) { /* No OP clocks --- VT clocks are used instead. */ @@ -264,7 +269,7 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *limits, * should run at higher clock rate, so smaller divisor is used * on video timing side. */ - if (limits->min_line_length_pck_bin > limits->min_line_length_pck + if (lim->min_line_length_pck_bin > lim->min_line_length_pck / pll->binning_horizontal) vt_op_binning_div = pll->binning_horizontal; else @@ -283,28 +288,28 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *limits, * 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->pix_clk_div * op_pll->sys_clk_div - * pll->scale_n, + 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); /* Find smallest and biggest allowed vt divisor. */ dev_dbg(dev, "min_vt_div: %u\n", min_vt_div); min_vt_div = max(min_vt_div, - DIV_ROUND_UP(pll->pll_op_clk_freq_hz, - limits->vt.max_pix_clk_freq_hz)); + DIV_ROUND_UP(op_pll_fr->pll_op_clk_freq_hz, + lim->vt_bk.max_pix_clk_freq_hz)); dev_dbg(dev, "min_vt_div: max_vt_pix_clk_freq_hz: %u\n", min_vt_div); min_vt_div = max_t(uint32_t, min_vt_div, - limits->vt.min_pix_clk_div - * limits->vt.min_sys_clk_div); + lim->vt_bk.min_pix_clk_div + * lim->vt_bk.min_sys_clk_div); dev_dbg(dev, "min_vt_div: min_vt_clk_div: %u\n", min_vt_div); - max_vt_div = limits->vt.max_sys_clk_div * limits->vt.max_pix_clk_div; + max_vt_div = lim->vt_bk.max_sys_clk_div * lim->vt_bk.max_pix_clk_div; dev_dbg(dev, "max_vt_div: %u\n", max_vt_div); max_vt_div = min(max_vt_div, - DIV_ROUND_UP(pll->pll_op_clk_freq_hz, - limits->vt.min_pix_clk_freq_hz)); + DIV_ROUND_UP(op_pll_fr->pll_op_clk_freq_hz, + lim->vt_bk.min_pix_clk_freq_hz)); dev_dbg(dev, "max_vt_div: min_vt_pix_clk_freq_hz: %u\n", max_vt_div); @@ -312,28 +317,28 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *limits, * Find limitsits for sys_clk_div. Not all values are possible * with all values of pix_clk_div. */ - min_sys_div = limits->vt.min_sys_clk_div; + min_sys_div = lim->vt_bk.min_sys_clk_div; dev_dbg(dev, "min_sys_div: %u\n", min_sys_div); min_sys_div = max(min_sys_div, DIV_ROUND_UP(min_vt_div, - limits->vt.max_pix_clk_div)); + lim->vt_bk.max_pix_clk_div)); dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %u\n", min_sys_div); min_sys_div = max(min_sys_div, - pll->pll_op_clk_freq_hz - / limits->vt.max_sys_clk_freq_hz); + op_pll_fr->pll_op_clk_freq_hz + / lim->vt_bk.max_sys_clk_freq_hz); dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %u\n", min_sys_div); min_sys_div = clk_div_even_up(min_sys_div); dev_dbg(dev, "min_sys_div: one or even: %u\n", min_sys_div); - max_sys_div = limits->vt.max_sys_clk_div; + max_sys_div = lim->vt_bk.max_sys_clk_div; dev_dbg(dev, "max_sys_div: %u\n", max_sys_div); max_sys_div = min(max_sys_div, DIV_ROUND_UP(max_vt_div, - limits->vt.min_pix_clk_div)); + lim->vt_bk.min_pix_clk_div)); dev_dbg(dev, "max_sys_div: min_vt_pix_clk_div: %u\n", max_sys_div); max_sys_div = min(max_sys_div, - DIV_ROUND_UP(pll->pll_op_clk_freq_hz, - limits->vt.min_pix_clk_freq_hz)); + DIV_ROUND_UP(op_pll_fr->pll_op_clk_freq_hz, + lim->vt_bk.min_pix_clk_freq_hz)); dev_dbg(dev, "max_sys_div: min_vt_pix_clk_freq_hz: %u\n", max_sys_div); /* @@ -348,13 +353,13 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *limits, sys_div += 2 - (sys_div & 1)) { uint16_t pix_div = DIV_ROUND_UP(vt_div, sys_div); - if (pix_div < limits->vt.min_pix_clk_div - || pix_div > limits->vt.max_pix_clk_div) { + if (pix_div < lim->vt_bk.min_pix_clk_div + || pix_div > lim->vt_bk.max_pix_clk_div) { dev_dbg(dev, "pix_div %u too small or too big (%u--%u)\n", pix_div, - limits->vt.min_pix_clk_div, - limits->vt.max_pix_clk_div); + lim->vt_bk.min_pix_clk_div, + lim->vt_bk.max_pix_clk_div); continue; } @@ -367,29 +372,32 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *limits, break; } - pll->vt.sys_clk_div = DIV_ROUND_UP(min_vt_div, best_pix_div); - pll->vt.pix_clk_div = best_pix_div; + pll->vt_bk.sys_clk_div = DIV_ROUND_UP(min_vt_div, best_pix_div); + pll->vt_bk.pix_clk_div = best_pix_div; - pll->vt.sys_clk_freq_hz = - pll->pll_op_clk_freq_hz / pll->vt.sys_clk_div; - pll->vt.pix_clk_freq_hz = - pll->vt.sys_clk_freq_hz / pll->vt.pix_clk_div; + pll->vt_bk.sys_clk_freq_hz = + op_pll_fr->pll_op_clk_freq_hz / pll->vt_bk.sys_clk_div; + pll->vt_bk.pix_clk_freq_hz = + pll->vt_bk.sys_clk_freq_hz / pll->vt_bk.pix_clk_div; out_skip_vt_calc: pll->pixel_rate_csi = - op_pll->pix_clk_freq_hz * lane_op_clock_ratio; - pll->pixel_rate_pixel_array = pll->vt.pix_clk_freq_hz; + op_pll_bk->pix_clk_freq_hz * lane_op_clock_ratio; + pll->pixel_rate_pixel_array = pll->vt_bk.pix_clk_freq_hz; - return check_all_bounds(dev, limits, op_limits, pll, op_pll); + return check_all_bounds(dev, lim, op_lim_fr, op_lim_bk, pll, op_pll_fr, + op_pll_bk); } -int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *limits, +int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, struct ccs_pll *pll) { - const struct ccs_pll_branch_limits *op_limits = &limits->op; - struct ccs_pll_branch *op_pll = &pll->op; - uint16_t min_pre_pll_clk_div; - uint16_t max_pre_pll_clk_div; + const struct ccs_pll_branch_limits_fr *op_lim_fr = &lim->vt_fr; + const struct ccs_pll_branch_limits_bk *op_lim_bk = &lim->op_bk; + struct ccs_pll_branch_fr *op_pll_fr = &pll->vt_fr; + 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; unsigned int i; @@ -401,8 +409,9 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *limits, * instead. The OP values are ignored for the rest of * the PLL calculation. */ - op_limits = &limits->vt; - op_pll = &pll->vt; + op_lim_fr = &lim->vt_fr; + op_lim_bk = &lim->vt_bk; + op_pll_bk = &pll->vt_bk; } if (pll->flags & CCS_PLL_FLAG_OP_PIX_CLOCK_PER_LANE) @@ -417,11 +426,11 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *limits, switch (pll->bus_type) { case CCS_PLL_BUS_TYPE_CSI2: /* CSI transfers 2 bits per clock per lane; thus times 2 */ - pll->pll_op_clk_freq_hz = pll->link_freq * 2 + op_pll_fr->pll_op_clk_freq_hz = pll->link_freq * 2 * (pll->csi2.lanes / lane_op_clock_ratio); break; case CCS_PLL_BUS_TYPE_PARALLEL: - pll->pll_op_clk_freq_hz = pll->link_freq * pll->bits_per_pixel + op_pll_fr->pll_op_clk_freq_hz = pll->link_freq * pll->bits_per_pixel / DIV_ROUND_UP(pll->bits_per_pixel, pll->parallel.bus_width); break; @@ -429,39 +438,40 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *limits, return -EINVAL; } - /* Figure out limits for pre-pll divider based on extclk */ - dev_dbg(dev, "min / max pre_pll_clk_div: %u / %u\n", - limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div); - max_pre_pll_clk_div = - min_t(uint16_t, limits->max_pre_pll_clk_div, + /* 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); + max_op_pre_pll_clk_div = + min_t(uint16_t, op_lim_fr->max_pre_pll_clk_div, clk_div_even(pll->ext_clk_freq_hz / - limits->min_pll_ip_freq_hz)); - min_pre_pll_clk_div = - max_t(uint16_t, limits->min_pre_pll_clk_div, + op_lim_fr->min_pll_ip_clk_freq_hz)); + min_op_pre_pll_clk_div = + max_t(uint16_t, op_lim_fr->min_pre_pll_clk_div, clk_div_even_up( DIV_ROUND_UP(pll->ext_clk_freq_hz, - limits->max_pll_ip_freq_hz))); - dev_dbg(dev, "pre-pll check: min / max pre_pll_clk_div: %u / %u\n", - min_pre_pll_clk_div, max_pre_pll_clk_div); + op_lim_fr->max_pll_ip_clk_freq_hz))); + dev_dbg(dev, "pre-pll check: min / max op_pre_pll_clk_div: %u / %u\n", + min_op_pre_pll_clk_div, max_op_pre_pll_clk_div); - i = gcd(pll->pll_op_clk_freq_hz, pll->ext_clk_freq_hz); - mul = pll->pll_op_clk_freq_hz / i; + i = gcd(op_pll_fr->pll_op_clk_freq_hz, pll->ext_clk_freq_hz); + mul = op_pll_fr->pll_op_clk_freq_hz / i; div = pll->ext_clk_freq_hz / i; dev_dbg(dev, "mul %u / div %u\n", mul, div); - min_pre_pll_clk_div = - max_t(uint16_t, min_pre_pll_clk_div, + min_op_pre_pll_clk_div = + max_t(uint16_t, min_op_pre_pll_clk_div, clk_div_even_up( DIV_ROUND_UP(mul * pll->ext_clk_freq_hz, - limits->max_pll_op_freq_hz))); - dev_dbg(dev, "pll_op check: min / max pre_pll_clk_div: %u / %u\n", - min_pre_pll_clk_div, max_pre_pll_clk_div); - - 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 = __ccs_pll_calculate(dev, limits, op_limits, pll, op_pll, - mul, div, lane_op_clock_ratio); + op_lim_fr->max_pll_op_clk_freq_hz))); + dev_dbg(dev, "pll_op check: min / max op_pre_pll_clk_div: %u / %u\n", + min_op_pre_pll_clk_div, max_op_pre_pll_clk_div); + + for (op_pll_fr->pre_pll_clk_div = min_op_pre_pll_clk_div; + 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); if (rval) continue; diff --git a/drivers/media/i2c/ccs-pll.h b/drivers/media/i2c/ccs-pll.h index 07f7f9e8a1cc..03b1d8d11423 100644 --- a/drivers/media/i2c/ccs-pll.h +++ b/drivers/media/i2c/ccs-pll.h @@ -20,7 +20,14 @@ #define CCS_PLL_FLAG_OP_PIX_CLOCK_PER_LANE (1 << 0) #define CCS_PLL_FLAG_NO_OP_CLOCKS (1 << 1) -struct ccs_pll_branch { +struct ccs_pll_branch_fr { + uint16_t pre_pll_clk_div; + uint16_t pll_multiplier; + uint32_t pll_ip_clk_freq_hz; + uint32_t pll_op_clk_freq_hz; +}; + +struct ccs_pll_branch_bk { uint16_t sys_clk_div; uint16_t pix_clk_div; uint32_t sys_clk_freq_hz; @@ -48,18 +55,26 @@ struct ccs_pll { uint32_t ext_clk_freq_hz; /* output values */ - uint16_t pre_pll_clk_div; - uint16_t pll_multiplier; - uint32_t pll_ip_clk_freq_hz; - uint32_t pll_op_clk_freq_hz; - struct ccs_pll_branch vt; - struct ccs_pll_branch op; + struct ccs_pll_branch_fr vt_fr; + struct ccs_pll_branch_bk vt_bk; + struct ccs_pll_branch_bk op_bk; uint32_t pixel_rate_csi; uint32_t pixel_rate_pixel_array; }; -struct ccs_pll_branch_limits { +struct ccs_pll_branch_limits_fr { + uint16_t min_pre_pll_clk_div; + uint16_t max_pre_pll_clk_div; + uint32_t min_pll_ip_clk_freq_hz; + uint32_t max_pll_ip_clk_freq_hz; + uint16_t min_pll_multiplier; + uint16_t max_pll_multiplier; + uint32_t min_pll_op_clk_freq_hz; + uint32_t max_pll_op_clk_freq_hz; +}; + +struct ccs_pll_branch_limits_bk { uint16_t min_sys_clk_div; uint16_t max_sys_clk_div; uint32_t min_sys_clk_freq_hz; @@ -74,17 +89,10 @@ struct ccs_pll_limits { /* Strict PLL limits */ uint32_t min_ext_clk_freq_hz; uint32_t max_ext_clk_freq_hz; - uint16_t min_pre_pll_clk_div; - uint16_t max_pre_pll_clk_div; - uint32_t min_pll_ip_freq_hz; - uint32_t max_pll_ip_freq_hz; - uint16_t min_pll_multiplier; - uint16_t max_pll_multiplier; - uint32_t min_pll_op_freq_hz; - uint32_t max_pll_op_freq_hz; - struct ccs_pll_branch_limits vt; - struct ccs_pll_branch_limits op; + struct ccs_pll_branch_limits_fr vt_fr; + struct ccs_pll_branch_limits_bk vt_bk; + struct ccs_pll_branch_limits_bk op_bk; /* Other relevant limits */ uint32_t min_line_length_pck_bin; diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index 4447ca367a84..00fb8edb8fc2 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -368,67 +368,70 @@ static int ccs_pll_configure(struct ccs_sensor *sensor) struct ccs_pll *pll = &sensor->pll; int rval; - rval = ccs_write(sensor, VT_PIX_CLK_DIV, pll->vt.pix_clk_div); + rval = ccs_write(sensor, VT_PIX_CLK_DIV, pll->vt_bk.pix_clk_div); if (rval < 0) return rval; - rval = ccs_write(sensor, VT_SYS_CLK_DIV, pll->vt.sys_clk_div); + rval = ccs_write(sensor, VT_SYS_CLK_DIV, pll->vt_bk.sys_clk_div); if (rval < 0) return rval; - rval = ccs_write(sensor, PRE_PLL_CLK_DIV, pll->pre_pll_clk_div); + rval = ccs_write(sensor, PRE_PLL_CLK_DIV, pll->vt_fr.pre_pll_clk_div); if (rval < 0) return rval; - rval = ccs_write(sensor, PLL_MULTIPLIER, pll->pll_multiplier); + rval = ccs_write(sensor, PLL_MULTIPLIER, pll->vt_fr.pll_multiplier); if (rval < 0) return rval; /* Lane op clock ratio does not apply here. */ rval = ccs_write(sensor, REQUESTED_LINK_RATE, - DIV_ROUND_UP(pll->op.sys_clk_freq_hz, + DIV_ROUND_UP(pll->op_bk.sys_clk_freq_hz, 1000000 / 256 / 256)); if (rval < 0 || sensor->pll.flags & CCS_PLL_FLAG_NO_OP_CLOCKS) return rval; - rval = ccs_write(sensor, OP_PIX_CLK_DIV, pll->op.pix_clk_div); + rval = ccs_write(sensor, OP_PIX_CLK_DIV, pll->op_bk.pix_clk_div); if (rval < 0) return rval; - return ccs_write(sensor, OP_SYS_CLK_DIV, pll->op.sys_clk_div); + return ccs_write(sensor, OP_SYS_CLK_DIV, pll->op_bk.sys_clk_div); } static int ccs_pll_try(struct ccs_sensor *sensor, struct ccs_pll *pll) { struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); struct ccs_pll_limits lim = { - .min_pre_pll_clk_div = CCS_LIM(sensor, MIN_PRE_PLL_CLK_DIV), - .max_pre_pll_clk_div = CCS_LIM(sensor, MAX_PRE_PLL_CLK_DIV), - .min_pll_ip_freq_hz = CCS_LIM(sensor, MIN_PLL_IP_CLK_FREQ_MHZ), - .max_pll_ip_freq_hz = CCS_LIM(sensor, MAX_PLL_IP_CLK_FREQ_MHZ), - .min_pll_multiplier = CCS_LIM(sensor, MIN_PLL_MULTIPLIER), - .max_pll_multiplier = CCS_LIM(sensor, MAX_PLL_MULTIPLIER), - .min_pll_op_freq_hz = CCS_LIM(sensor, MIN_PLL_OP_CLK_FREQ_MHZ), - .max_pll_op_freq_hz = CCS_LIM(sensor, MAX_PLL_OP_CLK_FREQ_MHZ), - - .op.min_sys_clk_div = CCS_LIM(sensor, MIN_OP_SYS_CLK_DIV), - .op.max_sys_clk_div = CCS_LIM(sensor, MAX_OP_SYS_CLK_DIV), - .op.min_pix_clk_div = CCS_LIM(sensor, MIN_OP_PIX_CLK_DIV), - .op.max_pix_clk_div = CCS_LIM(sensor, MAX_OP_PIX_CLK_DIV), - .op.min_sys_clk_freq_hz = CCS_LIM(sensor, MIN_OP_SYS_CLK_FREQ_MHZ), - .op.max_sys_clk_freq_hz = CCS_LIM(sensor, MAX_OP_SYS_CLK_FREQ_MHZ), - .op.min_pix_clk_freq_hz = CCS_LIM(sensor, MIN_OP_PIX_CLK_FREQ_MHZ), - .op.max_pix_clk_freq_hz = CCS_LIM(sensor, MAX_OP_PIX_CLK_FREQ_MHZ), - - .vt.min_sys_clk_div = CCS_LIM(sensor, MIN_VT_SYS_CLK_DIV), - .vt.max_sys_clk_div = CCS_LIM(sensor, MAX_VT_SYS_CLK_DIV), - .vt.min_pix_clk_div = CCS_LIM(sensor, MIN_VT_PIX_CLK_DIV), - .vt.max_pix_clk_div = CCS_LIM(sensor, MAX_VT_PIX_CLK_DIV), - .vt.min_sys_clk_freq_hz = CCS_LIM(sensor, MIN_VT_SYS_CLK_FREQ_MHZ), - .vt.max_sys_clk_freq_hz = CCS_LIM(sensor, MAX_VT_SYS_CLK_FREQ_MHZ), - .vt.min_pix_clk_freq_hz = CCS_LIM(sensor, MIN_VT_PIX_CLK_FREQ_MHZ), - .vt.max_pix_clk_freq_hz = CCS_LIM(sensor, MAX_VT_PIX_CLK_FREQ_MHZ), - + .vt_fr = { + .min_pre_pll_clk_div = CCS_LIM(sensor, MIN_PRE_PLL_CLK_DIV), + .max_pre_pll_clk_div = CCS_LIM(sensor, MAX_PRE_PLL_CLK_DIV), + .min_pll_ip_clk_freq_hz = CCS_LIM(sensor, MIN_PLL_IP_CLK_FREQ_MHZ), + .max_pll_ip_clk_freq_hz = CCS_LIM(sensor, MAX_PLL_IP_CLK_FREQ_MHZ), + .min_pll_multiplier = CCS_LIM(sensor, MIN_PLL_MULTIPLIER), + .max_pll_multiplier = CCS_LIM(sensor, MAX_PLL_MULTIPLIER), + .min_pll_op_clk_freq_hz = CCS_LIM(sensor, MIN_PLL_OP_CLK_FREQ_MHZ), + .max_pll_op_clk_freq_hz = CCS_LIM(sensor, MAX_PLL_OP_CLK_FREQ_MHZ), + }, + .op_bk = { + .min_sys_clk_div = CCS_LIM(sensor, MIN_OP_SYS_CLK_DIV), + .max_sys_clk_div = CCS_LIM(sensor, MAX_OP_SYS_CLK_DIV), + .min_pix_clk_div = CCS_LIM(sensor, MIN_OP_PIX_CLK_DIV), + .max_pix_clk_div = CCS_LIM(sensor, MAX_OP_PIX_CLK_DIV), + .min_sys_clk_freq_hz = CCS_LIM(sensor, MIN_OP_SYS_CLK_FREQ_MHZ), + .max_sys_clk_freq_hz = CCS_LIM(sensor, MAX_OP_SYS_CLK_FREQ_MHZ), + .min_pix_clk_freq_hz = CCS_LIM(sensor, MIN_OP_PIX_CLK_FREQ_MHZ), + .max_pix_clk_freq_hz = CCS_LIM(sensor, MAX_OP_PIX_CLK_FREQ_MHZ), + }, + .vt_bk = { + .min_sys_clk_div = CCS_LIM(sensor, MIN_VT_SYS_CLK_DIV), + .max_sys_clk_div = CCS_LIM(sensor, MAX_VT_SYS_CLK_DIV), + .min_pix_clk_div = CCS_LIM(sensor, MIN_VT_PIX_CLK_DIV), + .max_pix_clk_div = CCS_LIM(sensor, MAX_VT_PIX_CLK_DIV), + .min_sys_clk_freq_hz = CCS_LIM(sensor, MIN_VT_SYS_CLK_FREQ_MHZ), + .max_sys_clk_freq_hz = CCS_LIM(sensor, MAX_VT_SYS_CLK_FREQ_MHZ), + .min_pix_clk_freq_hz = CCS_LIM(sensor, MIN_VT_PIX_CLK_FREQ_MHZ), + .max_pix_clk_freq_hz = CCS_LIM(sensor, MAX_VT_PIX_CLK_FREQ_MHZ), + }, .min_line_length_pck_bin = CCS_LIM(sensor, MIN_LINE_LENGTH_PCK_BIN), .min_line_length_pck = CCS_LIM(sensor, MIN_LINE_LENGTH_PCK), }; From patchwork Wed Dec 2 18:06:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946573 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F23FEC71155 for ; Wed, 2 Dec 2020 18:11:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9DDCE22254 for ; Wed, 2 Dec 2020 18:11:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728926AbgLBSLY (ORCPT ); Wed, 2 Dec 2020 13:11:24 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48890 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728916AbgLBSLX (ORCPT ); Wed, 2 Dec 2020 13:11:23 -0500 Received: from hillosipuli.retiisi.eu (unknown [IPv6:2a01:4f9:c010:4572::e8:2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4B142C0613D4 for ; Wed, 2 Dec 2020 10:09:43 -0800 (PST) Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 17BDB634C8B; Wed, 2 Dec 2020 20:08:31 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 03/38] ccs-pll: Use correct VT divisor for calculating VT SYS divisor Date: Wed, 2 Dec 2020 20:06:06 +0200 Message-Id: <20201202180641.17401-4-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Use the correct video timing divisor to calculate the SYS divisor. Instead of the current value, the minimum was used. This could have resulted in a too low SYS divisor. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index b2f0fa14ff92..ea0f84fc8a90 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -365,14 +365,14 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, /* Check if this one is better. */ if (pix_div * sys_div - <= roundup(min_vt_div, best_pix_div)) + <= roundup(vt_div, best_pix_div)) best_pix_div = pix_div; } if (best_pix_div < INT_MAX >> 1) break; } - pll->vt_bk.sys_clk_div = DIV_ROUND_UP(min_vt_div, best_pix_div); + pll->vt_bk.sys_clk_div = DIV_ROUND_UP(vt_div, best_pix_div); pll->vt_bk.pix_clk_div = best_pix_div; pll->vt_bk.sys_clk_freq_hz = From patchwork Wed Dec 2 18:06:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946575 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 557FAC71156 for ; Wed, 2 Dec 2020 18:11:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 082AD221FC for ; Wed, 2 Dec 2020 18:11:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728945AbgLBSLY (ORCPT ); Wed, 2 Dec 2020 13:11:24 -0500 Received: from retiisi.eu ([95.216.213.190]:33484 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726283AbgLBSLY (ORCPT ); Wed, 2 Dec 2020 13:11:24 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 2811E634C8C; Wed, 2 Dec 2020 20:08:31 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 04/38] ccs-pll: End search if there are no better values available Date: Wed, 2 Dec 2020 20:06:07 +0200 Message-Id: <20201202180641.17401-5-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The VT divisor search can be ended if we've already found the value that corresponds exactly the total divisor, as there are no better (lower) values available. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index ea0f84fc8a90..22e29127804a 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -352,6 +352,7 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, sys_div <= max_sys_div; sys_div += 2 - (sys_div & 1)) { uint16_t pix_div = DIV_ROUND_UP(vt_div, sys_div); + uint16_t rounded_div; if (pix_div < lim->vt_bk.min_pix_clk_div || pix_div > lim->vt_bk.max_pix_clk_div) { @@ -363,10 +364,15 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, continue; } + rounded_div = roundup(vt_div, best_pix_div); + /* Check if this one is better. */ - if (pix_div * sys_div - <= roundup(vt_div, best_pix_div)) + if (pix_div * sys_div <= rounded_div) best_pix_div = pix_div; + + /* Bail out if we've already found the best value. */ + if (vt_div == rounded_div) + break; } if (best_pix_div < INT_MAX >> 1) break; From patchwork Wed Dec 2 18:06:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946583 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9C2D4C83013 for ; Wed, 2 Dec 2020 18:11:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 674D722240 for ; Wed, 2 Dec 2020 18:11:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728958AbgLBSL0 (ORCPT ); Wed, 2 Dec 2020 13:11:26 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48898 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728656AbgLBSLZ (ORCPT ); Wed, 2 Dec 2020 13:11:25 -0500 Received: from hillosipuli.retiisi.eu (unknown [IPv6:2a01:4f9:c010:4572::e8:2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4FC2EC0613D6 for ; Wed, 2 Dec 2020 10:09:45 -0800 (PST) Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 38871634C8E; Wed, 2 Dec 2020 20:08:31 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 05/38] ccs-pll: Remove parallel bus support Date: Wed, 2 Dec 2020 20:06:08 +0200 Message-Id: <20201202180641.17401-6-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The parallel bus PLL calculation has no users. Remove it. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 5 ----- drivers/media/i2c/ccs-pll.h | 14 ++++---------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index 22e29127804a..da97a2b91717 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -435,11 +435,6 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, op_pll_fr->pll_op_clk_freq_hz = pll->link_freq * 2 * (pll->csi2.lanes / lane_op_clock_ratio); break; - case CCS_PLL_BUS_TYPE_PARALLEL: - op_pll_fr->pll_op_clk_freq_hz = pll->link_freq * pll->bits_per_pixel - / DIV_ROUND_UP(pll->bits_per_pixel, - pll->parallel.bus_width); - break; default: return -EINVAL; } diff --git a/drivers/media/i2c/ccs-pll.h b/drivers/media/i2c/ccs-pll.h index 03b1d8d11423..578c9272688a 100644 --- a/drivers/media/i2c/ccs-pll.h +++ b/drivers/media/i2c/ccs-pll.h @@ -13,8 +13,7 @@ #define CCS_PLL_H /* CSI-2 or CCP-2 */ -#define CCS_PLL_BUS_TYPE_CSI2 0x00 -#define CCS_PLL_BUS_TYPE_PARALLEL 0x01 +#define CCS_PLL_BUS_TYPE_CSI2 0x00 /* op pix clock is for all lanes in total normally */ #define CCS_PLL_FLAG_OP_PIX_CLOCK_PER_LANE (1 << 0) @@ -37,14 +36,9 @@ struct ccs_pll_branch_bk { struct ccs_pll { /* input values */ uint8_t bus_type; - union { - struct { - uint8_t lanes; - } csi2; - struct { - uint8_t bus_width; - } parallel; - }; + struct { + uint8_t lanes; + } csi2; unsigned long flags; uint8_t binning_horizontal; uint8_t binning_vertical; From patchwork Wed Dec 2 18:06:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946571 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2C94BC64E7C for ; Wed, 2 Dec 2020 18:11:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C19F622240 for ; Wed, 2 Dec 2020 18:11:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389345AbgLBSLB (ORCPT ); Wed, 2 Dec 2020 13:11:01 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48828 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387580AbgLBSLA (ORCPT ); Wed, 2 Dec 2020 13:11:00 -0500 Received: from hillosipuli.retiisi.eu (unknown [IPv6:2a01:4f9:c010:4572::e8:2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 45848C0613CF for ; Wed, 2 Dec 2020 10:09:45 -0800 (PST) Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 488E9634C90; Wed, 2 Dec 2020 20:08:31 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 06/38] ccs-pll: Differentiate between CSI-2 D-PHY and C-PHY Date: Wed, 2 Dec 2020 20:06:09 +0200 Message-Id: <20201202180641.17401-7-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Differentiate between CSI-2 D-PHY and C-PHY. This does not yet include support for C-PHY. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 2 +- drivers/media/i2c/ccs-pll.h | 3 ++- drivers/media/i2c/ccs/ccs-core.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index da97a2b91717..c6435ed0597e 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -430,7 +430,7 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, pll->binning_vertical); switch (pll->bus_type) { - case CCS_PLL_BUS_TYPE_CSI2: + case CCS_PLL_BUS_TYPE_CSI2_DPHY: /* CSI transfers 2 bits per clock per lane; thus times 2 */ op_pll_fr->pll_op_clk_freq_hz = pll->link_freq * 2 * (pll->csi2.lanes / lane_op_clock_ratio); diff --git a/drivers/media/i2c/ccs-pll.h b/drivers/media/i2c/ccs-pll.h index 578c9272688a..d06a80c4fc52 100644 --- a/drivers/media/i2c/ccs-pll.h +++ b/drivers/media/i2c/ccs-pll.h @@ -13,7 +13,8 @@ #define CCS_PLL_H /* CSI-2 or CCP-2 */ -#define CCS_PLL_BUS_TYPE_CSI2 0x00 +#define CCS_PLL_BUS_TYPE_CSI2_DPHY 0x00 +#define CCS_PLL_BUS_TYPE_CSI2_CPHY 0x01 /* op pix clock is for all lanes in total normally */ #define CCS_PLL_FLAG_OP_PIX_CLOCK_PER_LANE (1 << 0) diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index 00fb8edb8fc2..591953cec6ec 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -3201,7 +3201,7 @@ static int ccs_probe(struct i2c_client *client) sensor->scale_m = CCS_LIM(sensor, SCALER_N_MIN); /* prepare PLL configuration input values */ - sensor->pll.bus_type = CCS_PLL_BUS_TYPE_CSI2; + sensor->pll.bus_type = CCS_PLL_BUS_TYPE_CSI2_DPHY; sensor->pll.csi2.lanes = sensor->hwcfg.lanes; sensor->pll.ext_clk_freq_hz = sensor->hwcfg.ext_clk; sensor->pll.scale_n = CCS_LIM(sensor, SCALER_N_MIN); From patchwork Wed Dec 2 18:06:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946581 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 674E1C83017 for ; Wed, 2 Dec 2020 18:11:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1CDB0205F4 for ; Wed, 2 Dec 2020 18:11:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387711AbgLBSLb (ORCPT ); Wed, 2 Dec 2020 13:11:31 -0500 Received: from retiisi.eu ([95.216.213.190]:33490 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728969AbgLBSL3 (ORCPT ); Wed, 2 Dec 2020 13:11:29 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 595B6634C91; Wed, 2 Dec 2020 20:08:31 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 07/38] ccs-pll: Move the flags field down, away from 8-bit fields Date: Wed, 2 Dec 2020 20:06:10 +0200 Message-Id: <20201202180641.17401-8-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org This way the struct will use less memory, with better packing and no waste due to unsigned long. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/ccs-pll.h b/drivers/media/i2c/ccs-pll.h index d06a80c4fc52..1d908b23c934 100644 --- a/drivers/media/i2c/ccs-pll.h +++ b/drivers/media/i2c/ccs-pll.h @@ -40,12 +40,12 @@ struct ccs_pll { struct { uint8_t lanes; } csi2; - unsigned long flags; uint8_t binning_horizontal; uint8_t binning_vertical; uint8_t scale_m; uint8_t scale_n; uint8_t bits_per_pixel; + uint16_t flags; uint32_t link_freq; uint32_t ext_clk_freq_hz; From patchwork Wed Dec 2 18:06:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946589 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 404C6C83014 for ; Wed, 2 Dec 2020 18:11:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DDF8822247 for ; Wed, 2 Dec 2020 18:11:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387580AbgLBSL2 (ORCPT ); Wed, 2 Dec 2020 13:11:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48904 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728900AbgLBSL1 (ORCPT ); Wed, 2 Dec 2020 13:11:27 -0500 Received: from hillosipuli.retiisi.eu (unknown [IPv6:2a01:4f9:c010:4572::e8:2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3B1FFC0617A6 for ; Wed, 2 Dec 2020 10:09:47 -0800 (PST) Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 69AB3634C92; Wed, 2 Dec 2020 20:08:31 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 08/38] ccs-pll: Document the structs in the header as well as the function Date: Wed, 2 Dec 2020 20:06:11 +0200 Message-Id: <20201202180641.17401-9-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The CCS pll is used by the CCS driver at the moment, but documenting the interface makes sense. It's non-trivial and the calculator could be used elsewhere. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.h | 89 +++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/drivers/media/i2c/ccs-pll.h b/drivers/media/i2c/ccs-pll.h index 1d908b23c934..1b8d36068c7d 100644 --- a/drivers/media/i2c/ccs-pll.h +++ b/drivers/media/i2c/ccs-pll.h @@ -20,6 +20,16 @@ #define CCS_PLL_FLAG_OP_PIX_CLOCK_PER_LANE (1 << 0) #define CCS_PLL_FLAG_NO_OP_CLOCKS (1 << 1) +/** + * struct ccs_pll_branch_fr - CCS PLL configuration (front) + * + * A single branch front-end of the CCS PLL tree. + * + * @pre_pll_clk_div: Pre-PLL clock divisor + * @pll_multiplier: PLL multiplier + * @pll_ip_clk_freq_hz: PLL input clock frequency + * @pll_op_clk_freq_hz: PLL output clock frequency + */ struct ccs_pll_branch_fr { uint16_t pre_pll_clk_div; uint16_t pll_multiplier; @@ -27,6 +37,16 @@ struct ccs_pll_branch_fr { uint32_t pll_op_clk_freq_hz; }; +/** + * struct ccs_pll_branch_bk - CCS PLL configuration (back) + * + * A single branch back-end of the CCS PLL tree. + * + * @sys_clk_div: System clock divider + * @pix_clk_div: Pixel clock divider + * @sys_clk_freq_hz: System clock frequency + * @pix_clk_freq_hz: Pixel clock frequency + */ struct ccs_pll_branch_bk { uint16_t sys_clk_div; uint16_t pix_clk_div; @@ -34,6 +54,30 @@ struct ccs_pll_branch_bk { uint32_t pix_clk_freq_hz; }; +/** + * struct ccs_pll - Full CCS PLL configuration + * + * All information required to calculate CCS PLL configuration. + * + * @bus_type: Type of the data bus, CCS_PLL_BUS_TYPE_* (input) + * @csi2: CSI-2 related parameters + * @csi2.lanes: The number of the CSI-2 data lanes (input) + * @binning_vertical: Vertical binning factor (input) + * @binning_horizontal: Horizontal binning factor (input) + * @scale_m: Downscaling factor, M component, [16, max] (input) + * @scale_n: Downscaling factor, N component, typically 16 (input) + * @bits_per_pixel: Bits per pixel on the output data bus (input) + * @flags: CCS_PLL_FLAG_* (input) + * @link_freq: Chosen link frequency (input) + * @ext_clk_freq_hz: External clock frequency, i.e. the sensor's input clock + * (input) + * @vt_fr: Video timing front-end configuration (output) + * @vt_bk: Video timing back-end configuration (output) + * @op_bk: Operational timing back-end configuration (output) + * @pixel_rate_csi: Pixel rate on the output data bus (output) + * @pixel_rate_pixel_array: Nominal pixel rate in the sensor's pixel array + * (output) + */ struct ccs_pll { /* input values */ uint8_t bus_type; @@ -58,6 +102,18 @@ struct ccs_pll { uint32_t pixel_rate_pixel_array; }; +/** + * struct ccs_pll_branch_limits_fr - CCS PLL front-end limits + * + * @min_pre_pll_clk_div: Minimum pre-PLL clock divider + * @max_pre_pll_clk_div: Maximum pre-PLL clock divider + * @min_pll_ip_clk_freq_hz: Minimum PLL input clock frequency + * @max_pll_ip_clk_freq_hz: Maximum PLL input clock frequency + * @min_pll_multiplier: Minimum PLL multiplier + * @max_pll_multiplier: Maximum PLL multiplier + * @min_pll_op_clk_freq_hz: Minimum PLL output clock frequency + * @max_pll_op_clk_freq_hz: Maximum PLL output clock frequency + */ struct ccs_pll_branch_limits_fr { uint16_t min_pre_pll_clk_div; uint16_t max_pre_pll_clk_div; @@ -69,6 +125,18 @@ struct ccs_pll_branch_limits_fr { uint32_t max_pll_op_clk_freq_hz; }; +/** + * struct ccs_pll_branch_limits_bk - CCS PLL back-end limits + * + * @min_sys_clk_div: Minimum system clock divider + * @max_sys_clk_div: Maximum system clock divider + * @min_sys_clk_freq_hz: Minimum system clock frequency + * @max_sys_clk_freq_hz: Maximum system clock frequency + * @min_pix_clk_div: Minimum pixel clock divider + * @max_pix_clk_div: Maximum pixel clock divider + * @min_pix_clk_freq_hz: Minimum pixel clock frequency + * @max_pix_clk_freq_hz: Maximum pixel clock frequency + */ struct ccs_pll_branch_limits_bk { uint16_t min_sys_clk_div; uint16_t max_sys_clk_div; @@ -80,6 +148,17 @@ struct ccs_pll_branch_limits_bk { uint32_t max_pix_clk_freq_hz; }; +/** + * struct ccs_pll_limits - CCS PLL limits + * + * @min_ext_clk_freq_hz: Minimum external clock frequency + * @max_ext_clk_freq_hz: Maximum external clock frequency + * @vt_fr: Video timing front-end limits + * @vt_bk: Video timing back-end limits + * @op_bk: Operational timing back-end limits + * @min_line_length_pck_bin: Minimum line length in pixels, with binning + * @min_line_length_pck: Minimum line length in pixels without binning + */ struct ccs_pll_limits { /* Strict PLL limits */ uint32_t min_ext_clk_freq_hz; @@ -96,6 +175,16 @@ struct ccs_pll_limits { struct device; +/** + * ccs_pll_calculate - Calculate CCS PLL configuration based on input parameters + * + * @dev: Device pointer, used for printing messages + * @limits: Limits specific to the sensor + * @pll: Given PLL configuration + * + * Calculate the CCS PLL configuration based on the limits as well as given + * device specific, system specific or user configured input data. + */ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *limits, struct ccs_pll *pll); From patchwork Wed Dec 2 18:06:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946593 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7ED04C8301A for ; Wed, 2 Dec 2020 18:11:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 21EDA221FC for ; Wed, 2 Dec 2020 18:11:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389352AbgLBSLc (ORCPT ); Wed, 2 Dec 2020 13:11:32 -0500 Received: from retiisi.eu ([95.216.213.190]:33494 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728979AbgLBSL2 (ORCPT ); Wed, 2 Dec 2020 13:11:28 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 7FD18634C93; Wed, 2 Dec 2020 20:08:31 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 09/38] ccs-pll: Use the BIT macro Date: Wed, 2 Dec 2020 20:06:12 +0200 Message-Id: <20201202180641.17401-10-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Use the BIT macro for setting individual bits. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.h b/drivers/media/i2c/ccs-pll.h index 1b8d36068c7d..3ad4e6524ab6 100644 --- a/drivers/media/i2c/ccs-pll.h +++ b/drivers/media/i2c/ccs-pll.h @@ -12,13 +12,16 @@ #ifndef CCS_PLL_H #define CCS_PLL_H +#include + /* CSI-2 or CCP-2 */ #define CCS_PLL_BUS_TYPE_CSI2_DPHY 0x00 #define CCS_PLL_BUS_TYPE_CSI2_CPHY 0x01 +/* Old SMIA and implementation specific flags */ /* op pix clock is for all lanes in total normally */ -#define CCS_PLL_FLAG_OP_PIX_CLOCK_PER_LANE (1 << 0) -#define CCS_PLL_FLAG_NO_OP_CLOCKS (1 << 1) +#define CCS_PLL_FLAG_OP_PIX_CLOCK_PER_LANE BIT(0) +#define CCS_PLL_FLAG_NO_OP_CLOCKS BIT(1) /** * struct ccs_pll_branch_fr - CCS PLL configuration (front) From patchwork Wed Dec 2 18:06:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946587 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.9 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8E8B2C83018 for ; Wed, 2 Dec 2020 18:11:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4CE25206D5 for ; Wed, 2 Dec 2020 18:11:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389356AbgLBSLc (ORCPT ); Wed, 2 Dec 2020 13:11:32 -0500 Received: from retiisi.eu ([95.216.213.190]:33496 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728656AbgLBSLa (ORCPT ); Wed, 2 Dec 2020 13:11:30 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 95303634C94; Wed, 2 Dec 2020 20:08:31 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 10/38] ccs-pll: Begin calculation from OP system clock frequency Date: Wed, 2 Dec 2020 20:06:13 +0200 Message-Id: <20201202180641.17401-11-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The OP system clock frequency defines the CSI-2 bus clock frequency, not the PLL output clock frequency. Both values were overwritten in the end, but the wrong limit value was used for the OP system clock frequency, possibly leading to too high frequencies being used. Also remove now duplicated calculation of OP system clock frequency later in the PLL calculator. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index c6435ed0597e..584be36f8c66 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -247,10 +247,6 @@ __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; - /* Derive pll_op_clk_freq_hz. */ - op_pll_bk->sys_clk_freq_hz = - op_pll_fr->pll_op_clk_freq_hz / op_pll_bk->sys_clk_div; - 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); @@ -432,7 +428,7 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, switch (pll->bus_type) { case CCS_PLL_BUS_TYPE_CSI2_DPHY: /* CSI transfers 2 bits per clock per lane; thus times 2 */ - op_pll_fr->pll_op_clk_freq_hz = pll->link_freq * 2 + op_pll_bk->sys_clk_freq_hz = pll->link_freq * 2 * (pll->csi2.lanes / lane_op_clock_ratio); break; default: @@ -454,8 +450,8 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, dev_dbg(dev, "pre-pll check: min / max op_pre_pll_clk_div: %u / %u\n", min_op_pre_pll_clk_div, max_op_pre_pll_clk_div); - i = gcd(op_pll_fr->pll_op_clk_freq_hz, pll->ext_clk_freq_hz); - mul = op_pll_fr->pll_op_clk_freq_hz / i; + i = gcd(op_pll_bk->sys_clk_freq_hz, pll->ext_clk_freq_hz); + mul = op_pll_bk->sys_clk_freq_hz / i; div = pll->ext_clk_freq_hz / i; dev_dbg(dev, "mul %u / div %u\n", mul, div); @@ -463,7 +459,7 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, max_t(uint16_t, min_op_pre_pll_clk_div, clk_div_even_up( DIV_ROUND_UP(mul * pll->ext_clk_freq_hz, - op_lim_fr->max_pll_op_clk_freq_hz))); + op_lim_bk->max_sys_clk_freq_hz))); dev_dbg(dev, "pll_op check: min / max op_pre_pll_clk_div: %u / %u\n", min_op_pre_pll_clk_div, max_op_pre_pll_clk_div); From patchwork Wed Dec 2 18:06:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946585 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B79A1C83019 for ; Wed, 2 Dec 2020 18:11:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7A8CB205F4 for ; Wed, 2 Dec 2020 18:11:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389359AbgLBSLc (ORCPT ); Wed, 2 Dec 2020 13:11:32 -0500 Received: from retiisi.eu ([95.216.213.190]:33498 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387603AbgLBSLc (ORCPT ); Wed, 2 Dec 2020 13:11:32 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id AA89D634C95; Wed, 2 Dec 2020 20:08:31 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 11/38] ccs-pll: Fix condition for pre-PLL divider lower bound Date: Wed, 2 Dec 2020 20:06:14 +0200 Message-Id: <20201202180641.17401-12-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The lower bound of the pre-PLL divider was calculated based on OP SYS clock frequency which is also affected by the OP SYS clock divider. This is wrong. The right clock frequency is that of the PLL output clock. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index 584be36f8c66..b45e6b30c528 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -459,7 +459,7 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, max_t(uint16_t, min_op_pre_pll_clk_div, clk_div_even_up( DIV_ROUND_UP(mul * pll->ext_clk_freq_hz, - op_lim_bk->max_sys_clk_freq_hz))); + op_lim_fr->max_pll_op_clk_freq_hz))); dev_dbg(dev, "pll_op check: min / max op_pre_pll_clk_div: %u / %u\n", min_op_pre_pll_clk_div, max_op_pre_pll_clk_div); From patchwork Wed Dec 2 18:06:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946591 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4C3FAC71155 for ; Wed, 2 Dec 2020 18:11:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E2D13205F4 for ; Wed, 2 Dec 2020 18:11:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728900AbgLBSLd (ORCPT ); Wed, 2 Dec 2020 13:11:33 -0500 Received: from retiisi.eu ([95.216.213.190]:33504 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387621AbgLBSLc (ORCPT ); Wed, 2 Dec 2020 13:11:32 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id BF359634C96; Wed, 2 Dec 2020 20:08:31 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 12/38] ccs-pll: Avoid overflow in pre-PLL divisor lower bound search Date: Wed, 2 Dec 2020 20:06:15 +0200 Message-Id: <20201202180641.17401-13-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The external clock frequency times the PLL multiplier may exceed the value range of 32-bit unsigned integers. Instead perform the same calculation y using two divisions. The result has some potential to be different, but that's ok: this number is used to limit the range of pre-PLL divisors to find optimal values. So the effect of the rare case of a different result here would mean an invalid pre-PLL divisor is tried. That will be found out a little later in any case. Also guard against dividing by zero if the external clock frequency is higher than the maximum OP PLL output clock --- a rather improbable case. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index b45e6b30c528..78897a7c1448 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -40,6 +40,11 @@ static inline uint32_t is_one_or_even(uint32_t a) return 1; } +static inline uint32_t one_or_more(uint32_t a) +{ + return a ?: 1; +} + static int bounds_check(struct device *dev, uint32_t val, uint32_t min, uint32_t max, char *str) { @@ -458,8 +463,10 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, min_op_pre_pll_clk_div = max_t(uint16_t, min_op_pre_pll_clk_div, clk_div_even_up( - DIV_ROUND_UP(mul * pll->ext_clk_freq_hz, - op_lim_fr->max_pll_op_clk_freq_hz))); + mul / + one_or_more( + DIV_ROUND_UP(op_lim_fr->max_pll_op_clk_freq_hz, + pll->ext_clk_freq_hz)))); dev_dbg(dev, "pll_op check: min / max op_pre_pll_clk_div: %u / %u\n", min_op_pre_pll_clk_div, max_op_pre_pll_clk_div); From patchwork Wed Dec 2 18:06:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946609 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 54C81C64E7B for ; Wed, 2 Dec 2020 18:13:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 09FFB22240 for ; Wed, 2 Dec 2020 18:13:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730542AbgLBSNI (ORCPT ); Wed, 2 Dec 2020 13:13:08 -0500 Received: from retiisi.eu ([95.216.213.190]:33612 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728241AbgLBSNI (ORCPT ); Wed, 2 Dec 2020 13:13:08 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id D3B41634C97; Wed, 2 Dec 2020 20:08:31 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 13/38] ccs-pll: Fix comment on check against maximum PLL multiplier Date: Wed, 2 Dec 2020 20:06:16 +0200 Message-Id: <20201202180641.17401-14-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The comment is about minimum PLL multiplier but the related check really deals with the maximum PLL multiplier. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index 78897a7c1448..f4c41d61e332 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -203,7 +203,7 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, / div); dev_dbg(dev, "more_mul_max: max_op_sys_clk_div check: %u\n", more_mul_max); - /* Ensure we won't go above min_pll_multiplier. */ + /* Ensure we won't go above max_pll_multiplier. */ more_mul_max = min(more_mul_max, DIV_ROUND_UP(op_lim_fr->max_pll_multiplier, mul)); dev_dbg(dev, "more_mul_max: min_pll_multiplier check: %u\n", From patchwork Wed Dec 2 18:06:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946597 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 60A21C64E7C for ; Wed, 2 Dec 2020 18:12:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E7CA2206D5 for ; Wed, 2 Dec 2020 18:12:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387767AbgLBSMl (ORCPT ); Wed, 2 Dec 2020 13:12:41 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48898 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387531AbgLBSMl (ORCPT ); Wed, 2 Dec 2020 13:12:41 -0500 Received: from hillosipuli.retiisi.eu (unknown [IPv6:2a01:4f9:c010:4572::e8:2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CE3CFC0613CF for ; Wed, 2 Dec 2020 10:11:25 -0800 (PST) Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id E7009634C98; Wed, 2 Dec 2020 20:08:31 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 14/38] ccs-pll: Fix check for PLL multiplier upper bound Date: Wed, 2 Dec 2020 20:06:17 +0200 Message-Id: <20201202180641.17401-15-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The additional multiplier (for higher VT timing) of the PLL multiplier was checked against the upper limit but the result was rounded up, possibly producing too high additional multiplier. Round down instead to keep within hardware limits. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index f4c41d61e332..b23e959000a4 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -204,8 +204,7 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, dev_dbg(dev, "more_mul_max: max_op_sys_clk_div check: %u\n", more_mul_max); /* Ensure we won't go above max_pll_multiplier. */ - more_mul_max = min(more_mul_max, - DIV_ROUND_UP(op_lim_fr->max_pll_multiplier, mul)); + more_mul_max = min(more_mul_max, op_lim_fr->max_pll_multiplier / mul); dev_dbg(dev, "more_mul_max: min_pll_multiplier check: %u\n", more_mul_max); From patchwork Wed Dec 2 18:06:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946613 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DD8E5C71155 for ; Wed, 2 Dec 2020 18:13:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8AB59221FC for ; Wed, 2 Dec 2020 18:13:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729406AbgLBSNH (ORCPT ); Wed, 2 Dec 2020 13:13:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49172 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729090AbgLBSNG (ORCPT ); Wed, 2 Dec 2020 13:13:06 -0500 Received: from hillosipuli.retiisi.eu (unknown [IPv6:2a01:4f9:c010:4572::e8:2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5959FC0613D4 for ; Wed, 2 Dec 2020 10:11:26 -0800 (PST) Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 0671E634C99; Wed, 2 Dec 2020 20:08:32 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 15/38] ccs-pll: Use explicit 32-bit unsigned type Date: Wed, 2 Dec 2020 20:06:18 +0200 Message-Id: <20201202180641.17401-16-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Use uint32_t instead of unsigned int for a variable that contains explicitly 32-bit numbers. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index b23e959000a4..d33a2575329c 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -177,7 +177,7 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, uint32_t more_mul_factor; uint32_t min_vt_div, max_vt_div, vt_div; uint32_t min_sys_div, max_sys_div; - unsigned int i; + uint32_t i; /* * Get pre_pll_clk_div so that our pll_op_clk_freq_hz won't be @@ -406,7 +406,7 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, uint16_t max_op_pre_pll_clk_div; uint32_t lane_op_clock_ratio; uint32_t mul, div; - unsigned int i; + uint32_t i; int rval = -EINVAL; if (pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) { From patchwork Wed Dec 2 18:06:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946615 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3E769C71156 for ; Wed, 2 Dec 2020 18:13:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E8F15221FC for ; Wed, 2 Dec 2020 18:13:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387599AbgLBSNJ (ORCPT ); Wed, 2 Dec 2020 13:13:09 -0500 Received: from retiisi.eu ([95.216.213.190]:33618 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729086AbgLBSNI (ORCPT ); Wed, 2 Dec 2020 13:13:08 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 1A6BB634CA1; Wed, 2 Dec 2020 20:08:32 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 16/38] ccs-pll: Add support for lane speed model Date: Wed, 2 Dec 2020 20:06:19 +0200 Message-Id: <20201202180641.17401-17-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org 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 --- drivers/media/i2c/ccs-pll.c | 36 +++++++++++++++++++++++++----------- drivers/media/i2c/ccs-pll.h | 6 ++++++ 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index d33a2575329c..9750b49d834a 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -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); diff --git a/drivers/media/i2c/ccs-pll.h b/drivers/media/i2c/ccs-pll.h index 3ad4e6524ab6..fe8eb3d4bcff 100644 --- a/drivers/media/i2c/ccs-pll.h +++ b/drivers/media/i2c/ccs-pll.h @@ -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; From patchwork Wed Dec 2 18:06:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946611 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CF2D5C64E7C for ; Wed, 2 Dec 2020 18:13:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7F788206D5 for ; Wed, 2 Dec 2020 18:13:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387531AbgLBSNJ (ORCPT ); Wed, 2 Dec 2020 13:13:09 -0500 Received: from retiisi.eu ([95.216.213.190]:33622 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729090AbgLBSNI (ORCPT ); Wed, 2 Dec 2020 13:13:08 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 30519634CA3; Wed, 2 Dec 2020 20:08:32 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 17/38] ccs: Add support for lane speed model Date: Wed, 2 Dec 2020 20:06:20 +0200 Message-Id: <20201202180641.17401-18-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Convey the relevant PLL flags to the PLL calculator. Also the lane speed model affects how the link rate is calculated on the CSI-2 bus, as the rate is total of all lanes. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs/ccs-core.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index 591953cec6ec..f3d4209c818c 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -387,7 +387,9 @@ static int ccs_pll_configure(struct ccs_sensor *sensor) /* Lane op clock ratio does not apply here. */ rval = ccs_write(sensor, REQUESTED_LINK_RATE, DIV_ROUND_UP(pll->op_bk.sys_clk_freq_hz, - 1000000 / 256 / 256)); + 1000000 / 256 / 256) * + (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ? + sensor->pll.csi2.lanes : 1)); if (rval < 0 || sensor->pll.flags & CCS_PLL_FLAG_NO_OP_CLOCKS) return rval; @@ -3203,6 +3205,13 @@ static int ccs_probe(struct i2c_client *client) /* prepare PLL configuration input values */ sensor->pll.bus_type = CCS_PLL_BUS_TYPE_CSI2_DPHY; 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; + } sensor->pll.ext_clk_freq_hz = sensor->hwcfg.ext_clk; sensor->pll.scale_n = CCS_LIM(sensor, SCALER_N_MIN); From patchwork Wed Dec 2 18:06:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946617 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EA386C83013 for ; Wed, 2 Dec 2020 18:13:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9BF0122248 for ; Wed, 2 Dec 2020 18:13:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387710AbgLBSNK (ORCPT ); Wed, 2 Dec 2020 13:13:10 -0500 Received: from retiisi.eu ([95.216.213.190]:33624 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730455AbgLBSNJ (ORCPT ); Wed, 2 Dec 2020 13:13:09 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 46239634CA4; Wed, 2 Dec 2020 20:08:32 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 18/38] ccs-pll: Add support for decoupled OP domain calculation Date: Wed, 2 Dec 2020 20:06:21 +0200 Message-Id: <20201202180641.17401-19-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org 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 --- drivers/media/i2c/ccs-pll.c | 22 +++++++--------------- drivers/media/i2c/ccs-pll.h | 1 + drivers/media/i2c/ccs/ccs-core.c | 14 +++++++++++--- drivers/media/i2c/ccs/ccs-quirk.c | 5 ++++- 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index 9750b49d834a..cb19a36e54df 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -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; diff --git a/drivers/media/i2c/ccs-pll.h b/drivers/media/i2c/ccs-pll.h index fe8eb3d4bcff..fe20af11a068 100644 --- a/drivers/media/i2c/ccs-pll.h +++ b/drivers/media/i2c/ccs-pll.h @@ -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) diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index f3d4209c818c..41c006ad03c4 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -3207,10 +3207,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); diff --git a/drivers/media/i2c/ccs/ccs-quirk.c b/drivers/media/i2c/ccs/ccs-quirk.c index 4fe8c6f70579..e3d4c7a275bc 100644 --- a/drivers/media/i2c/ccs/ccs-quirk.c +++ b/drivers/media/i2c/ccs/ccs-quirk.c @@ -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; } From patchwork Wed Dec 2 18:06:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946619 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3D34EC64E7B for ; Wed, 2 Dec 2020 18:13:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E397822248 for ; Wed, 2 Dec 2020 18:13:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387881AbgLBSNL (ORCPT ); Wed, 2 Dec 2020 13:13:11 -0500 Received: from retiisi.eu ([95.216.213.190]:33628 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728241AbgLBSNL (ORCPT ); Wed, 2 Dec 2020 13:13:11 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 5E301634CA5; Wed, 2 Dec 2020 20:08:32 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 19/38] ccs-pll: Add support for extended input PLL clock divider Date: Wed, 2 Dec 2020 20:06:22 +0200 Message-Id: <20201202180641.17401-20-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org CCS allows odd PLL dividers other than 1, granted that the corresponding capability bit is set. Support this both in the PLL calculator and the CCS driver. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 4 +++- drivers/media/i2c/ccs-pll.h | 1 + drivers/media/i2c/ccs/ccs-core.c | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index cb19a36e54df..62939ca5b8e2 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -478,7 +478,9 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, for (op_pll_fr->pre_pll_clk_div = min_op_pre_pll_clk_div; 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)) { + op_pll_fr->pre_pll_clk_div += + (pll->flags & CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER) ? 1 : + 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); if (rval) diff --git a/drivers/media/i2c/ccs-pll.h b/drivers/media/i2c/ccs-pll.h index fe20af11a068..807ae7250aa2 100644 --- a/drivers/media/i2c/ccs-pll.h +++ b/drivers/media/i2c/ccs-pll.h @@ -25,6 +25,7 @@ /* CCS PLL flags */ #define CCS_PLL_FLAG_LANE_SPEED_MODEL BIT(2) #define CCS_PLL_FLAG_LINK_DECOUPLED BIT(3) +#define CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER BIT(4) /** * struct ccs_pll_branch_fr - CCS PLL configuration (front) diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index 41c006ad03c4..70f4f304fef6 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -3220,6 +3220,9 @@ static int ccs_probe(struct i2c_client *client) sensor->pll.op_lanes = sensor->pll.csi2.lanes; } } + if (CCS_LIM(sensor, CLOCK_TREE_PLL_CAPABILITY) & + CCS_CLOCK_TREE_PLL_CAPABILITY_EXT_DIVIDER) + sensor->pll.flags |= CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER; sensor->pll.ext_clk_freq_hz = sensor->hwcfg.ext_clk; sensor->pll.scale_n = CCS_LIM(sensor, SCALER_N_MIN); From patchwork Wed Dec 2 18:06:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946601 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6CC2CC64E7B for ; Wed, 2 Dec 2020 18:12:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1B92B22248 for ; Wed, 2 Dec 2020 18:12:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729033AbgLBSMu (ORCPT ); Wed, 2 Dec 2020 13:12:50 -0500 Received: from retiisi.eu ([95.216.213.190]:33494 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729032AbgLBSMt (ORCPT ); Wed, 2 Dec 2020 13:12:49 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 735DE634CA9; Wed, 2 Dec 2020 20:08:32 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 20/38] ccs-pll: Support two cycles per pixel on OP domain Date: Wed, 2 Dec 2020 20:06:23 +0200 Message-Id: <20201202180641.17401-21-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The l parameter defines the number of clock cycles to process a single pixel per OP lane. It is calculated based on a new register op_bits_per_lane. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 19 +++++++++++++------ drivers/media/i2c/ccs-pll.h | 2 ++ drivers/media/i2c/ccs/ccs-core.c | 1 + 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index 62939ca5b8e2..60ab0c043c7a 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -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 div, uint32_t l) { uint32_t sys_div; uint32_t best_pix_div = INT_MAX >> 1; @@ -252,10 +252,15 @@ __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 - * pll->op_lanes / pll->csi2.lanes; + if (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL) + op_pll_bk->pix_clk_div = pll->bits_per_pixel + * pll->op_lanes / pll->csi2.lanes / l; + else + op_pll_bk->pix_clk_div = pll->bits_per_pixel / l; + 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) { @@ -291,7 +296,7 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, 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 - * pll->vt_lanes, + * pll->vt_lanes * l, pll->op_lanes * vt_op_binning_div * pll->scale_m); @@ -406,6 +411,8 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, uint16_t min_op_pre_pll_clk_div; uint16_t max_op_pre_pll_clk_div; uint32_t mul, div; + uint32_t l = (!pll->op_bits_per_lane || + pll->op_bits_per_lane >= pll->bits_per_pixel) ? 1 : 2; uint32_t i; int rval = -EINVAL; @@ -444,7 +451,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); + pll->csi2.lanes : 1) / l; /* Figure out limits for OP pre-pll divider based on extclk */ dev_dbg(dev, "min / max op_pre_pll_clk_div: %u / %u\n", @@ -482,7 +489,7 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, (pll->flags & CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER) ? 1 : 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); + op_pll_fr, op_pll_bk, mul, div, l); if (rval) continue; diff --git a/drivers/media/i2c/ccs-pll.h b/drivers/media/i2c/ccs-pll.h index 807ae7250aa2..207822cf2324 100644 --- a/drivers/media/i2c/ccs-pll.h +++ b/drivers/media/i2c/ccs-pll.h @@ -76,6 +76,7 @@ struct ccs_pll_branch_bk { * @scale_m: Downscaling factor, M component, [16, max] (input) * @scale_n: Downscaling factor, N component, typically 16 (input) * @bits_per_pixel: Bits per pixel on the output data bus (input) + * @op_bits_per_lane: Number of bits per OP lane (input) * @flags: CCS_PLL_FLAG_* (input) * @link_freq: Chosen link frequency (input) * @ext_clk_freq_hz: External clock frequency, i.e. the sensor's input clock @@ -100,6 +101,7 @@ struct ccs_pll { uint8_t scale_m; uint8_t scale_n; uint8_t bits_per_pixel; + uint8_t op_bits_per_lane; uint16_t flags; uint32_t link_freq; uint32_t ext_clk_freq_hz; diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index 70f4f304fef6..83de43fa1880 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -3223,6 +3223,7 @@ static int ccs_probe(struct i2c_client *client) if (CCS_LIM(sensor, CLOCK_TREE_PLL_CAPABILITY) & CCS_CLOCK_TREE_PLL_CAPABILITY_EXT_DIVIDER) sensor->pll.flags |= CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER; + 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); From patchwork Wed Dec 2 18:06:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946605 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E6D9DC71156 for ; Wed, 2 Dec 2020 18:12:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 98C71206D5 for ; Wed, 2 Dec 2020 18:12:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729054AbgLBSMv (ORCPT ); Wed, 2 Dec 2020 13:12:51 -0500 Received: from retiisi.eu ([95.216.213.190]:33490 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727454AbgLBSMu (ORCPT ); Wed, 2 Dec 2020 13:12:50 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 8AC80634CAA; Wed, 2 Dec 2020 20:08:32 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 21/38] ccs-pll: Add support flexible OP PLL pixel clock divider Date: Wed, 2 Dec 2020 20:06:24 +0200 Message-Id: <20201202180641.17401-22-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Flexible OP PLL pixel clock divider allows a higher OP pixel clock than what the bus can transfer. This generally makes it easier to select pixel clock dividers. This changes how the pixel rate on the bus and minimum VT divisor are calculated, as the pixel rate is no longer directly determined by the OP pixel clock and the number of the lanes. Also add a sanity check for sensors that do not support flexible OP PLL pixel clock divider. This could have caused the PLL calculator to come up with an invalid configuration for those devices. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 26 +++++++++++++++++++------- drivers/media/i2c/ccs-pll.h | 1 + drivers/media/i2c/ccs/ccs-core.c | 4 +++- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index 60ab0c043c7a..e3a6493fd601 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -294,11 +294,11 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, * 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 - * pll->vt_lanes * l, - pll->op_lanes * vt_op_binning_div - * 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, + (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ? + pll->csi2.lanes : 1) + * vt_op_binning_div * pll->scale_m); /* Find smallest and biggest allowed vt divisor. */ dev_dbg(dev, "min_vt_div: %u\n", min_vt_div); @@ -420,6 +420,18 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, pll->op_lanes = 1; pll->vt_lanes = 1; } + + /* + * Make sure op_pix_clk_div will be integer --- unless flexible + * op_pix_clk_div is supported + */ + if (!(pll->flags & CCS_PLL_FLAG_FLEXIBLE_OP_PIX_CLK_DIV) && + (pll->bits_per_pixel * pll->op_lanes) % (pll->csi2.lanes * l)) { + dev_dbg(dev, "op_pix_clk_div not an integer (bpp %u, op lanes %u, lanes %u, l %u)\n", + pll->bits_per_pixel, pll->op_lanes, pll->csi2.lanes, l); + return -EINVAL; + } + dev_dbg(dev, "vt_lanes: %u\n", pll->vt_lanes); dev_dbg(dev, "op_lanes: %u\n", pll->op_lanes); @@ -449,9 +461,9 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, } pll->pixel_rate_csi = - op_pll_bk->pix_clk_freq_hz + op_pll_bk->sys_clk_freq_hz * (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ? - pll->csi2.lanes : 1) / l; + pll->csi2.lanes : 1) / pll->bits_per_pixel / l; /* Figure out limits for OP pre-pll divider based on extclk */ dev_dbg(dev, "min / max op_pre_pll_clk_div: %u / %u\n", diff --git a/drivers/media/i2c/ccs-pll.h b/drivers/media/i2c/ccs-pll.h index 207822cf2324..1b5c20736fe8 100644 --- a/drivers/media/i2c/ccs-pll.h +++ b/drivers/media/i2c/ccs-pll.h @@ -26,6 +26,7 @@ #define CCS_PLL_FLAG_LANE_SPEED_MODEL BIT(2) #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) /** * struct ccs_pll_branch_fr - CCS PLL configuration (front) diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index 83de43fa1880..95d274834f0e 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -30,7 +30,6 @@ #include #include "ccs.h" -#include "ccs-limits.h" #define CCS_ALIGN_DIM(dim, flags) \ ((flags) & V4L2_SEL_FLAG_GE \ @@ -3223,6 +3222,9 @@ static int ccs_probe(struct i2c_client *client) if (CCS_LIM(sensor, CLOCK_TREE_PLL_CAPABILITY) & CCS_CLOCK_TREE_PLL_CAPABILITY_EXT_DIVIDER) sensor->pll.flags |= CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER; + 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; 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); From patchwork Wed Dec 2 18:06:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946599 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2C302C64E7C for ; Wed, 2 Dec 2020 18:12:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CAE2B206D5 for ; Wed, 2 Dec 2020 18:12:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387616AbgLBSMu (ORCPT ); Wed, 2 Dec 2020 13:12:50 -0500 Received: from retiisi.eu ([95.216.213.190]:33496 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729012AbgLBSMt (ORCPT ); Wed, 2 Dec 2020 13:12:49 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 9D4C4634CBD; Wed, 2 Dec 2020 20:08:32 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 22/38] ccs-pll: Add sanity checks Date: Wed, 2 Dec 2020 20:06:25 +0200 Message-Id: <20201202180641.17401-23-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add sanity checks for fields that could cause division by zero. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index e3a6493fd601..420d2c4d7b2c 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -421,6 +421,15 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, pll->vt_lanes = 1; } + if (!pll->op_lanes || !pll->vt_lanes || !pll->bits_per_pixel || + !pll->ext_clk_freq_hz || !pll->link_freq || !pll->scale_m || + !op_lim_fr->min_pll_ip_clk_freq_hz || + !op_lim_fr->max_pll_ip_clk_freq_hz || + !op_lim_fr->min_pll_op_clk_freq_hz || + !op_lim_fr->max_pll_op_clk_freq_hz || + !op_lim_bk->max_sys_clk_div || !op_lim_fr->max_pll_multiplier) + return -EINVAL; + /* * Make sure op_pix_clk_div will be integer --- unless flexible * op_pix_clk_div is supported From patchwork Wed Dec 2 18:06:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946603 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 083C1C71155 for ; Wed, 2 Dec 2020 18:12:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A3558206D5 for ; Wed, 2 Dec 2020 18:12:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387790AbgLBSMu (ORCPT ); Wed, 2 Dec 2020 13:12:50 -0500 Received: from retiisi.eu ([95.216.213.190]:33498 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729033AbgLBSMt (ORCPT ); Wed, 2 Dec 2020 13:12:49 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id AF8D7634CBE; Wed, 2 Dec 2020 20:08:32 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 23/38] ccs-pll: Add C-PHY support Date: Wed, 2 Dec 2020 20:06:26 +0200 Message-Id: <20201202180641.17401-24-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add C-PHY support for the CCS PLL calculator. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index 420d2c4d7b2c..0fa7c6f67195 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -145,6 +145,10 @@ static int check_all_bounds(struct device *dev, return rval; } +#define CPHY_CONST 7 +#define DPHY_CONST 16 +#define PHY_CONST_DIV 16 + /* * Heuristically guess the PLL tree for a given common multiplier and * divisor. Begin with the operational timing and continue to video @@ -162,7 +166,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 l) + uint32_t div, uint32_t l, bool cphy, uint32_t phy_const) { uint32_t sys_div; uint32_t best_pix_div = INT_MAX >> 1; @@ -254,9 +258,11 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, if (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL) op_pll_bk->pix_clk_div = pll->bits_per_pixel - * pll->op_lanes / pll->csi2.lanes / l; + * pll->op_lanes * phy_const + / PHY_CONST_DIV / pll->csi2.lanes / l; else - op_pll_bk->pix_clk_div = pll->bits_per_pixel / l; + op_pll_bk->pix_clk_div = + pll->bits_per_pixel * phy_const / PHY_CONST_DIV / l; op_pll_bk->pix_clk_freq_hz = op_pll_bk->sys_clk_freq_hz / op_pll_bk->pix_clk_div; @@ -295,10 +301,11 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, */ 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, + * 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); + * 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); @@ -408,6 +415,8 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, const struct ccs_pll_branch_limits_bk *op_lim_bk = &lim->op_bk; struct ccs_pll_branch_fr *op_pll_fr = &pll->vt_fr; struct ccs_pll_branch_bk *op_pll_bk = &pll->op_bk; + bool cphy = pll->bus_type == CCS_PLL_BUS_TYPE_CSI2_CPHY; + uint32_t phy_const = cphy ? CPHY_CONST : DPHY_CONST; uint16_t min_op_pre_pll_clk_div; uint16_t max_op_pre_pll_clk_div; uint32_t mul, div; @@ -465,14 +474,21 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, * (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ? 1 : pll->csi2.lanes); break; + case CCS_PLL_BUS_TYPE_CSI2_CPHY: + op_pll_bk->sys_clk_freq_hz = + pll->link_freq + * (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ? + 1 : pll->csi2.lanes); + break; default: return -EINVAL; } pll->pixel_rate_csi = - op_pll_bk->sys_clk_freq_hz - * (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ? - pll->csi2.lanes : 1) / pll->bits_per_pixel / l; + div_u64((uint64_t)op_pll_bk->sys_clk_freq_hz + * (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ? + pll->csi2.lanes : 1) * PHY_CONST_DIV, + phy_const * pll->bits_per_pixel * l); /* Figure out limits for OP pre-pll divider based on extclk */ dev_dbg(dev, "min / max op_pre_pll_clk_div: %u / %u\n", @@ -510,7 +526,8 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, (pll->flags & CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER) ? 1 : 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, l); + op_pll_fr, op_pll_bk, mul, div, l, + cphy, phy_const); if (rval) continue; From patchwork Wed Dec 2 18:06:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946607 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C87F3C64E7C for ; Wed, 2 Dec 2020 18:12:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7851822240 for ; Wed, 2 Dec 2020 18:12:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729047AbgLBSMv (ORCPT ); Wed, 2 Dec 2020 13:12:51 -0500 Received: from retiisi.eu ([95.216.213.190]:33504 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729035AbgLBSMv (ORCPT ); Wed, 2 Dec 2020 13:12:51 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id B76EF634CBF; Wed, 2 Dec 2020 20:08:32 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 24/38] ccs-pll: Split off VT subtree calculation Date: Wed, 2 Dec 2020 20:06:27 +0200 Message-Id: <20201202180641.17401-25-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Split off the VT sub clock tree calculation from the rest, into its own function. Also call the op_pll_fr argument pll_fr, since soon these may not be OP tree values. This paves way for additional features in the future such as dual PLL support. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 255 ++++++++++++++++++------------------ 1 file changed, 131 insertions(+), 124 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index 0fa7c6f67195..3d43e737155f 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -149,130 +149,18 @@ static int check_all_bounds(struct device *dev, #define DPHY_CONST 16 #define PHY_CONST_DIV 16 -/* - * Heuristically guess the PLL tree for a given common multiplier and - * divisor. Begin with the operational timing and continue to video - * timing once operational timing has been verified. - * - * @mul is the PLL multiplier and @div is the common divisor - * (pre_pll_clk_div and op_sys_clk_div combined). The final PLL - * multiplier will be a multiple of @mul. - * - * @return Zero on success, error code on error. - */ -static int -__ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, - const struct ccs_pll_branch_limits_fr *op_lim_fr, - 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 l, bool cphy, uint32_t phy_const) +static void +__ccs_pll_calculate_vt(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 *pll_fr, + struct ccs_pll_branch_bk *op_pll_bk, bool cphy, + uint32_t phy_const) { uint32_t sys_div; uint32_t best_pix_div = INT_MAX >> 1; uint32_t vt_op_binning_div; - /* - * Higher multipliers (and divisors) are often required than - * necessitated by the external clock and the output clocks. - * There are limits for all values in the clock tree. These - * are the minimum and maximum multiplier for mul. - */ - uint32_t more_mul_min, more_mul_max; - uint32_t more_mul_factor; uint32_t min_vt_div, max_vt_div, vt_div; uint32_t min_sys_div, max_sys_div; - uint32_t i; - - /* - * Get pre_pll_clk_div so that our pll_op_clk_freq_hz won't be - * too high. - */ - dev_dbg(dev, "op_pre_pll_clk_div %u\n", op_pll_fr->pre_pll_clk_div); - - /* Don't go above max pll multiplier. */ - more_mul_max = op_lim_fr->max_pll_multiplier / mul; - dev_dbg(dev, "more_mul_max: max_op_pll_multiplier check: %u\n", - more_mul_max); - /* Don't go above max pll op frequency. */ - more_mul_max = - 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)); - 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. */ - more_mul_max = min(more_mul_max, - op_lim_bk->max_sys_clk_div * op_pll_fr->pre_pll_clk_div - / div); - dev_dbg(dev, "more_mul_max: max_op_sys_clk_div check: %u\n", - more_mul_max); - /* Ensure we won't go above max_pll_multiplier. */ - more_mul_max = min(more_mul_max, op_lim_fr->max_pll_multiplier / mul); - dev_dbg(dev, "more_mul_max: min_pll_multiplier check: %u\n", - more_mul_max); - - /* Ensure we won't go below min_pll_op_clk_freq_hz. */ - more_mul_min = DIV_ROUND_UP(op_lim_fr->min_pll_op_clk_freq_hz, - pll->ext_clk_freq_hz / - op_pll_fr->pre_pll_clk_div * mul); - dev_dbg(dev, "more_mul_min: min_op_pll_op_clk_freq_hz check: %u\n", - more_mul_min); - /* Ensure we won't go below min_pll_multiplier. */ - more_mul_min = max(more_mul_min, - DIV_ROUND_UP(op_lim_fr->min_pll_multiplier, mul)); - dev_dbg(dev, "more_mul_min: min_op_pll_multiplier check: %u\n", - more_mul_min); - - if (more_mul_min > more_mul_max) { - dev_dbg(dev, - "unable to compute more_mul_min and more_mul_max\n"); - return -EINVAL; - } - - more_mul_factor = lcm(div, op_pll_fr->pre_pll_clk_div) / div; - dev_dbg(dev, "more_mul_factor: %u\n", more_mul_factor); - more_mul_factor = lcm(more_mul_factor, op_lim_bk->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)) - i <<= 1; - - dev_dbg(dev, "final more_mul: %u\n", i); - if (i > more_mul_max) { - dev_dbg(dev, "final more_mul is bad, max %u\n", more_mul_max); - return -EINVAL; - } - - op_pll_fr->pll_multiplier = mul * i; - op_pll_bk->sys_clk_div = div * i / op_pll_fr->pre_pll_clk_div; - dev_dbg(dev, "op_sys_clk_div: %u\n", op_pll_bk->sys_clk_div); - - op_pll_fr->pll_ip_clk_freq_hz = pll->ext_clk_freq_hz - / op_pll_fr->pre_pll_clk_div; - - op_pll_fr->pll_op_clk_freq_hz = op_pll_fr->pll_ip_clk_freq_hz - * op_pll_fr->pll_multiplier; - - if (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL) - op_pll_bk->pix_clk_div = pll->bits_per_pixel - * pll->op_lanes * phy_const - / PHY_CONST_DIV / pll->csi2.lanes / l; - else - op_pll_bk->pix_clk_div = - pll->bits_per_pixel * phy_const / PHY_CONST_DIV / l; - - 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. */ - goto out_skip_vt_calc; - } /* * Some sensors perform analogue binning and some do this @@ -310,7 +198,7 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, /* Find smallest and biggest allowed vt divisor. */ dev_dbg(dev, "min_vt_div: %u\n", min_vt_div); min_vt_div = max(min_vt_div, - DIV_ROUND_UP(op_pll_fr->pll_op_clk_freq_hz, + DIV_ROUND_UP(pll_fr->pll_op_clk_freq_hz, lim->vt_bk.max_pix_clk_freq_hz)); dev_dbg(dev, "min_vt_div: max_vt_pix_clk_freq_hz: %u\n", min_vt_div); @@ -322,7 +210,7 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, max_vt_div = lim->vt_bk.max_sys_clk_div * lim->vt_bk.max_pix_clk_div; dev_dbg(dev, "max_vt_div: %u\n", max_vt_div); max_vt_div = min(max_vt_div, - DIV_ROUND_UP(op_pll_fr->pll_op_clk_freq_hz, + DIV_ROUND_UP(pll_fr->pll_op_clk_freq_hz, lim->vt_bk.min_pix_clk_freq_hz)); dev_dbg(dev, "max_vt_div: min_vt_pix_clk_freq_hz: %u\n", max_vt_div); @@ -338,7 +226,7 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, lim->vt_bk.max_pix_clk_div)); dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %u\n", min_sys_div); min_sys_div = max(min_sys_div, - op_pll_fr->pll_op_clk_freq_hz + pll_fr->pll_op_clk_freq_hz / lim->vt_bk.max_sys_clk_freq_hz); dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %u\n", min_sys_div); min_sys_div = clk_div_even_up(min_sys_div); @@ -351,7 +239,7 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, lim->vt_bk.min_pix_clk_div)); dev_dbg(dev, "max_sys_div: min_vt_pix_clk_div: %u\n", max_sys_div); max_sys_div = min(max_sys_div, - DIV_ROUND_UP(op_pll_fr->pll_op_clk_freq_hz, + DIV_ROUND_UP(pll_fr->pll_op_clk_freq_hz, lim->vt_bk.min_pix_clk_freq_hz)); dev_dbg(dev, "max_sys_div: min_vt_pix_clk_freq_hz: %u\n", max_sys_div); @@ -396,11 +284,130 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, pll->vt_bk.pix_clk_div = best_pix_div; pll->vt_bk.sys_clk_freq_hz = - op_pll_fr->pll_op_clk_freq_hz / pll->vt_bk.sys_clk_div; + pll_fr->pll_op_clk_freq_hz / pll->vt_bk.sys_clk_div; pll->vt_bk.pix_clk_freq_hz = pll->vt_bk.sys_clk_freq_hz / pll->vt_bk.pix_clk_div; +} + +/* + * Heuristically guess the PLL tree for a given common multiplier and + * divisor. Begin with the operational timing and continue to video + * timing once operational timing has been verified. + * + * @mul is the PLL multiplier and @div is the common divisor + * (pre_pll_clk_div and op_sys_clk_div combined). The final PLL + * multiplier will be a multiple of @mul. + * + * @return Zero on success, error code on error. + */ +static int +__ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, + const struct ccs_pll_branch_limits_fr *op_lim_fr, + 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 l, bool cphy, uint32_t phy_const) +{ + /* + * Higher multipliers (and divisors) are often required than + * necessitated by the external clock and the output clocks. + * There are limits for all values in the clock tree. These + * are the minimum and maximum multiplier for mul. + */ + uint32_t more_mul_min, more_mul_max; + uint32_t more_mul_factor; + uint32_t i; + + /* + * Get pre_pll_clk_div so that our pll_op_clk_freq_hz won't be + * too high. + */ + dev_dbg(dev, "op_pre_pll_clk_div %u\n", op_pll_fr->pre_pll_clk_div); + + /* Don't go above max pll multiplier. */ + more_mul_max = op_lim_fr->max_pll_multiplier / mul; + dev_dbg(dev, "more_mul_max: max_op_pll_multiplier check: %u\n", + more_mul_max); + /* Don't go above max pll op frequency. */ + more_mul_max = + 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)); + 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. */ + more_mul_max = min(more_mul_max, + op_lim_bk->max_sys_clk_div * op_pll_fr->pre_pll_clk_div + / div); + dev_dbg(dev, "more_mul_max: max_op_sys_clk_div check: %u\n", + more_mul_max); + /* Ensure we won't go above max_pll_multiplier. */ + more_mul_max = min(more_mul_max, op_lim_fr->max_pll_multiplier / mul); + dev_dbg(dev, "more_mul_max: min_pll_multiplier check: %u\n", + more_mul_max); + + /* Ensure we won't go below min_pll_op_clk_freq_hz. */ + more_mul_min = DIV_ROUND_UP(op_lim_fr->min_pll_op_clk_freq_hz, + pll->ext_clk_freq_hz / + op_pll_fr->pre_pll_clk_div * mul); + dev_dbg(dev, "more_mul_min: min_op_pll_op_clk_freq_hz check: %u\n", + more_mul_min); + /* Ensure we won't go below min_pll_multiplier. */ + more_mul_min = max(more_mul_min, + DIV_ROUND_UP(op_lim_fr->min_pll_multiplier, mul)); + dev_dbg(dev, "more_mul_min: min_op_pll_multiplier check: %u\n", + more_mul_min); + + if (more_mul_min > more_mul_max) { + dev_dbg(dev, + "unable to compute more_mul_min and more_mul_max\n"); + return -EINVAL; + } + + more_mul_factor = lcm(div, op_pll_fr->pre_pll_clk_div) / div; + dev_dbg(dev, "more_mul_factor: %u\n", more_mul_factor); + more_mul_factor = lcm(more_mul_factor, op_lim_bk->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)) + i <<= 1; + + dev_dbg(dev, "final more_mul: %u\n", i); + if (i > more_mul_max) { + dev_dbg(dev, "final more_mul is bad, max %u\n", more_mul_max); + return -EINVAL; + } + + op_pll_fr->pll_multiplier = mul * i; + op_pll_bk->sys_clk_div = div * i / op_pll_fr->pre_pll_clk_div; + dev_dbg(dev, "op_sys_clk_div: %u\n", op_pll_bk->sys_clk_div); + + op_pll_fr->pll_ip_clk_freq_hz = pll->ext_clk_freq_hz + / op_pll_fr->pre_pll_clk_div; + + op_pll_fr->pll_op_clk_freq_hz = op_pll_fr->pll_ip_clk_freq_hz + * op_pll_fr->pll_multiplier; + + if (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL) + op_pll_bk->pix_clk_div = pll->bits_per_pixel + * pll->op_lanes * phy_const + / PHY_CONST_DIV / pll->csi2.lanes / l; + else + op_pll_bk->pix_clk_div = + pll->bits_per_pixel * phy_const / PHY_CONST_DIV / l; + + 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)) + __ccs_pll_calculate_vt(dev, lim, op_lim_bk, pll, op_pll_fr, + op_pll_bk, cphy, phy_const); -out_skip_vt_calc: pll->pixel_rate_pixel_array = pll->vt_bk.pix_clk_freq_hz * pll->vt_lanes; From patchwork Wed Dec 2 18:06:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946629 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4B000C8300F for ; Wed, 2 Dec 2020 18:14:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E7D5C22249 for ; Wed, 2 Dec 2020 18:14:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389149AbgLBSOJ (ORCPT ); Wed, 2 Dec 2020 13:14:09 -0500 Received: from retiisi.eu ([95.216.213.190]:33496 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387739AbgLBSOI (ORCPT ); Wed, 2 Dec 2020 13:14:08 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id D100E634CC0; Wed, 2 Dec 2020 20:08:32 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 25/38] ccs-pll: Check for derating and overrating, support non-derating sensors Date: Wed, 2 Dec 2020 20:06:28 +0200 Message-Id: <20201202180641.17401-26-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org 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 --- drivers/media/i2c/ccs-pll.c | 84 +++++++++++++++++++++----------- drivers/media/i2c/ccs-pll.h | 2 + drivers/media/i2c/ccs/ccs-core.c | 7 +++ 3 files changed, 64 insertions(+), 29 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index 3d43e737155f..96eb71f16c81 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -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); diff --git a/drivers/media/i2c/ccs-pll.h b/drivers/media/i2c/ccs-pll.h index 1b5c20736fe8..03c2428c76cd 100644 --- a/drivers/media/i2c/ccs-pll.h +++ b/drivers/media/i2c/ccs-pll.h @@ -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) diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index 95d274834f0e..849c1001e3cc 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -3225,6 +3225,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); From patchwork Wed Dec 2 18:06:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946621 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 03D64C64E7C for ; Wed, 2 Dec 2020 18:14:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 99F32206D5 for ; Wed, 2 Dec 2020 18:14:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389070AbgLBSOH (ORCPT ); Wed, 2 Dec 2020 13:14:07 -0500 Received: from retiisi.eu ([95.216.213.190]:33494 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387885AbgLBSOH (ORCPT ); Wed, 2 Dec 2020 13:14:07 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id E6F4A634CC1; Wed, 2 Dec 2020 20:08:32 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 26/38] ccs-pll: Better separate OP and VT sub-tree calculation Date: Wed, 2 Dec 2020 20:06:29 +0200 Message-Id: <20201202180641.17401-27-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Better separate OP PLL branch calculation from VT branch calculation. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 54 +++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index 96eb71f16c81..e879c03a3d3b 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -162,11 +162,11 @@ static int check_all_bounds(struct device *dev, #define PHY_CONST_DIV 16 static void -__ccs_pll_calculate_vt(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 *pll_fr, - struct ccs_pll_branch_bk *op_pll_bk, bool cphy, - uint32_t phy_const) +ccs_pll_calculate_vt(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 *pll_fr, + struct ccs_pll_branch_bk *op_pll_bk, bool cphy, + uint32_t phy_const) { uint32_t sys_div; uint32_t best_pix_div = INT_MAX >> 1; @@ -174,6 +174,9 @@ __ccs_pll_calculate_vt(struct device *dev, const struct ccs_pll_limits *lim, uint32_t min_vt_div, max_vt_div, vt_div; uint32_t min_sys_div, max_sys_div; + if (pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) + goto out_calc_pixel_rate; + /* * Find out whether a sensor supports derating. If it does not, VT and * OP domains are required to run at the same pixel rate. @@ -313,6 +316,10 @@ __ccs_pll_calculate_vt(struct device *dev, const struct ccs_pll_limits *lim, pll_fr->pll_op_clk_freq_hz / pll->vt_bk.sys_clk_div; pll->vt_bk.pix_clk_freq_hz = pll->vt_bk.sys_clk_freq_hz / pll->vt_bk.pix_clk_div; + +out_calc_pixel_rate: + pll->pixel_rate_pixel_array = + pll->vt_bk.pix_clk_freq_hz * pll->vt_lanes; } /* @@ -327,12 +334,12 @@ __ccs_pll_calculate_vt(struct device *dev, const struct ccs_pll_limits *lim, * @return Zero on success, error code on error. */ static int -__ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, - const struct ccs_pll_branch_limits_fr *op_lim_fr, - 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 l, bool cphy, uint32_t phy_const) +ccs_pll_calculate_op(struct device *dev, const struct ccs_pll_limits *lim, + const struct ccs_pll_branch_limits_fr *op_lim_fr, + 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 l, bool cphy, uint32_t phy_const) { /* * Higher multipliers (and divisors) are often required than @@ -430,15 +437,7 @@ __ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, dev_dbg(dev, "op_pix_clk_div: %u\n", op_pll_bk->pix_clk_div); - if (!(pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS)) - __ccs_pll_calculate_vt(dev, lim, op_lim_bk, pll, op_pll_fr, - op_pll_bk, cphy, phy_const); - - 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); + return 0; } int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, @@ -558,13 +557,22 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, op_pll_fr->pre_pll_clk_div += (pll->flags & CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER) ? 1 : 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, l, - cphy, phy_const); + rval = ccs_pll_calculate_op(dev, lim, op_lim_fr, op_lim_bk, pll, + op_pll_fr, op_pll_bk, mul, div, l, + cphy, phy_const); + if (rval) + continue; + + ccs_pll_calculate_vt(dev, lim, op_lim_bk, pll, op_pll_fr, + op_pll_bk, cphy, phy_const); + + rval = check_all_bounds(dev, lim, op_lim_fr, op_lim_bk, pll, + op_pll_fr, op_pll_bk); if (rval) continue; print_pll(dev, pll); + return 0; } From patchwork Wed Dec 2 18:06:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946623 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5771BC64E7B for ; Wed, 2 Dec 2020 18:14:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E6506206D5 for ; Wed, 2 Dec 2020 18:14:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389108AbgLBSOJ (ORCPT ); Wed, 2 Dec 2020 13:14:09 -0500 Received: from retiisi.eu ([95.216.213.190]:33498 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387843AbgLBSOI (ORCPT ); Wed, 2 Dec 2020 13:14:08 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 07EC2634CCA; Wed, 2 Dec 2020 20:08:33 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 27/38] ccs-pll: Print relevant information on PLL tree Date: Wed, 2 Dec 2020 20:06:30 +0200 Message-Id: <20201202180641.17401-28-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Print information on PLL tree configuration based on the flags. This also adds support for printing dual PLL trees, and better separates between OP and VT PLL trees. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 85 ++++++++++++++++++++++++++++--------- 1 file changed, 66 insertions(+), 19 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index e879c03a3d3b..43735f6d0bb2 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -56,28 +56,75 @@ static int bounds_check(struct device *dev, uint32_t val, return -EINVAL; } -static void print_pll(struct device *dev, struct ccs_pll *pll) +#define PLL_OP 1 +#define PLL_VT 2 + +static const char *pll_string(unsigned int which) { - dev_dbg(dev, "pre_pll_clk_div\t%u\n", pll->vt_fr.pre_pll_clk_div); - dev_dbg(dev, "pll_multiplier \t%u\n", pll->vt_fr.pll_multiplier); - if (!(pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS)) { - dev_dbg(dev, "op_sys_clk_div \t%u\n", pll->op_bk.sys_clk_div); - dev_dbg(dev, "op_pix_clk_div \t%u\n", pll->op_bk.pix_clk_div); + switch (which) { + case PLL_OP: + return "op"; + case PLL_VT: + return "vt"; } - dev_dbg(dev, "vt_sys_clk_div \t%u\n", pll->vt_bk.sys_clk_div); - dev_dbg(dev, "vt_pix_clk_div \t%u\n", pll->vt_bk.pix_clk_div); - - dev_dbg(dev, "ext_clk_freq_hz \t%u\n", pll->ext_clk_freq_hz); - dev_dbg(dev, "pll_ip_clk_freq_hz \t%u\n", pll->vt_fr.pll_ip_clk_freq_hz); - dev_dbg(dev, "pll_op_clk_freq_hz \t%u\n", pll->vt_fr.pll_op_clk_freq_hz); - if (!(pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS)) { - dev_dbg(dev, "op_sys_clk_freq_hz \t%u\n", - pll->op_bk.sys_clk_freq_hz); - dev_dbg(dev, "op_pix_clk_freq_hz \t%u\n", - pll->op_bk.pix_clk_freq_hz); + + return NULL; +} + +#define PLL_FL(f) CCS_PLL_FLAG_##f + +static void print_pll(struct device *dev, struct ccs_pll *pll) +{ + const struct { + struct ccs_pll_branch_fr *fr; + struct ccs_pll_branch_bk *bk; + unsigned int which; + } branches[] = { + { &pll->vt_fr, &pll->vt_bk, PLL_VT }, + { NULL, &pll->op_bk, PLL_OP } + }, *br; + unsigned int i; + + dev_dbg(dev, "ext_clk_freq_hz\t\t%u\n", pll->ext_clk_freq_hz); + + for (i = 0, br = branches; i < ARRAY_SIZE(branches); i++, br++) { + const char *s = pll_string(br->which); + + if (br->which == PLL_VT) { + dev_dbg(dev, "%s_pre_pll_clk_div\t\t%u\n", s, + br->fr->pre_pll_clk_div); + dev_dbg(dev, "%s_pll_multiplier\t\t%u\n", s, + br->fr->pll_multiplier); + + dev_dbg(dev, "%s_pll_ip_clk_freq_hz\t%u\n", s, + br->fr->pll_ip_clk_freq_hz); + dev_dbg(dev, "%s_pll_op_clk_freq_hz\t%u\n", s, + br->fr->pll_op_clk_freq_hz); + } + + if (!(pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) || + br->which == PLL_VT) { + dev_dbg(dev, "%s_sys_clk_div\t\t%u\n", s, + br->bk->sys_clk_div); + dev_dbg(dev, "%s_pix_clk_div\t\t%u\n", s, + br->bk->pix_clk_div); + + dev_dbg(dev, "%s_sys_clk_freq_hz\t%u\n", s, + br->bk->sys_clk_freq_hz); + dev_dbg(dev, "%s_pix_clk_freq_hz\t%u\n", s, + br->bk->pix_clk_freq_hz); + } } - dev_dbg(dev, "vt_sys_clk_freq_hz \t%u\n", pll->vt_bk.sys_clk_freq_hz); - dev_dbg(dev, "vt_pix_clk_freq_hz \t%u\n", pll->vt_bk.pix_clk_freq_hz); + + dev_dbg(dev, "flags%s%s%s%s%s%s\n", + pll->flags & PLL_FL(LANE_SPEED_MODEL) ? " lane-speed" : "", + pll->flags & PLL_FL(LINK_DECOUPLED) ? " link-decoupled" : "", + pll->flags & PLL_FL(EXT_IP_PLL_DIVIDER) ? + " ext-ip-pll-divider" : "", + pll->flags & PLL_FL(FLEXIBLE_OP_PIX_CLK_DIV) ? + " flexible-op-pix-div" : "", + pll->flags & PLL_FL(FIFO_DERATING) ? " fifo-derating" : "", + pll->flags & PLL_FL(FIFO_OVERRATING) ? " fifo-overrating" : ""); } static int check_all_bounds(struct device *dev, From patchwork Wed Dec 2 18:06:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946625 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AADCBC71156 for ; Wed, 2 Dec 2020 18:14:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5F35A22249 for ; Wed, 2 Dec 2020 18:14:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389179AbgLBSOJ (ORCPT ); Wed, 2 Dec 2020 13:14:09 -0500 Received: from retiisi.eu ([95.216.213.190]:33490 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388302AbgLBSOI (ORCPT ); Wed, 2 Dec 2020 13:14:08 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 1B8B2634CCC; Wed, 2 Dec 2020 20:08:33 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 28/38] ccs-pll: Rework bounds checks Date: Wed, 2 Dec 2020 20:06:31 +0200 Message-Id: <20201202180641.17401-29-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Refactor bounds checks so that the caller can decide what to check. This allows doing the checks early, when the values are available. This also adds front OP PLL configuration and limits. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 148 ++++++++++++++++++++++-------------- drivers/media/i2c/ccs-pll.h | 4 + 2 files changed, 95 insertions(+), 57 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index 43735f6d0bb2..a6443589b948 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -46,12 +46,14 @@ static inline uint32_t one_or_more(uint32_t a) } static int bounds_check(struct device *dev, uint32_t val, - uint32_t min, uint32_t max, char *str) + uint32_t min, uint32_t max, const char *prefix, + char *str) { if (val >= min && val <= max) return 0; - dev_dbg(dev, "%s out of bounds: %d (%d--%d)\n", str, val, min, max); + dev_dbg(dev, "%s_%s out of bounds: %d (%d--%d)\n", prefix, + str, val, min, max); return -EINVAL; } @@ -81,7 +83,7 @@ static void print_pll(struct device *dev, struct ccs_pll *pll) unsigned int which; } branches[] = { { &pll->vt_fr, &pll->vt_bk, PLL_VT }, - { NULL, &pll->op_bk, PLL_OP } + { &pll->op_fr, &pll->op_bk, PLL_OP } }, *br; unsigned int i; @@ -127,68 +129,90 @@ static void print_pll(struct device *dev, struct ccs_pll *pll) pll->flags & PLL_FL(FIFO_OVERRATING) ? " fifo-overrating" : ""); } -static int check_all_bounds(struct device *dev, - const struct ccs_pll_limits *lim, - const struct ccs_pll_branch_limits_fr *op_lim_fr, - 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) +static int check_fr_bounds(struct device *dev, + const struct ccs_pll_limits *lim, + struct ccs_pll *pll, unsigned int which) { + const struct ccs_pll_branch_limits_fr *lim_fr; + struct ccs_pll_branch_fr *pll_fr; + const char *s = pll_string(which); int rval; - rval = bounds_check(dev, op_pll_fr->pll_ip_clk_freq_hz, - op_lim_fr->min_pll_ip_clk_freq_hz, - op_lim_fr->max_pll_ip_clk_freq_hz, - "pll_ip_clk_freq_hz"); - if (!rval) - rval = bounds_check( - dev, op_pll_fr->pll_multiplier, - op_lim_fr->min_pll_multiplier, - op_lim_fr->max_pll_multiplier, "pll_multiplier"); - if (!rval) - rval = bounds_check( - dev, op_pll_fr->pll_op_clk_freq_hz, - op_lim_fr->min_pll_op_clk_freq_hz, - op_lim_fr->max_pll_op_clk_freq_hz, "pll_op_clk_freq_hz"); + if (which == PLL_OP) { + lim_fr = &lim->op_fr; + pll_fr = &pll->op_fr; + } else { + lim_fr = &lim->vt_fr; + pll_fr = &pll->vt_fr; + } + + rval = bounds_check(dev, pll_fr->pre_pll_clk_div, + lim_fr->min_pre_pll_clk_div, + lim_fr->max_pre_pll_clk_div, s, "pre_pll_clk_div"); + if (!rval) - rval = bounds_check( - dev, op_pll_bk->sys_clk_div, - op_lim_bk->min_sys_clk_div, op_lim_bk->max_sys_clk_div, - "op_sys_clk_div"); + rval = bounds_check(dev, pll_fr->pll_ip_clk_freq_hz, + lim_fr->min_pll_ip_clk_freq_hz, + lim_fr->max_pll_ip_clk_freq_hz, + s, "pll_ip_clk_freq_hz"); if (!rval) - rval = bounds_check( - dev, op_pll_bk->sys_clk_freq_hz, - op_lim_bk->min_sys_clk_freq_hz, - op_lim_bk->max_sys_clk_freq_hz, - "op_sys_clk_freq_hz"); + rval = bounds_check(dev, pll_fr->pll_multiplier, + lim_fr->min_pll_multiplier, + lim_fr->max_pll_multiplier, + s, "pll_multiplier"); if (!rval) - rval = bounds_check( - dev, op_pll_bk->pix_clk_freq_hz, - op_lim_bk->min_pix_clk_freq_hz, - op_lim_bk->max_pix_clk_freq_hz, - "op_pix_clk_freq_hz"); + rval = bounds_check(dev, pll_fr->pll_op_clk_freq_hz, + lim_fr->min_pll_op_clk_freq_hz, + lim_fr->max_pll_op_clk_freq_hz, + s, "pll_op_clk_freq_hz"); - /* - * If there are no OP clocks, the VT clocks are contained in - * the OP clock struct. - */ - if (pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) - return rval; + return rval; +} + +static int check_bk_bounds(struct device *dev, + const struct ccs_pll_limits *lim, + struct ccs_pll *pll, unsigned int which) +{ + const struct ccs_pll_branch_limits_bk *lim_bk; + struct ccs_pll_branch_bk *pll_bk; + const char *s = pll_string(which); + int rval; + + if (which == PLL_OP) { + if (pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) + return 0; + lim_bk = &lim->op_bk; + pll_bk = &pll->op_bk; + } else { + lim_bk = &lim->vt_bk; + pll_bk = &pll->vt_bk; + } + + rval = bounds_check(dev, pll_bk->sys_clk_div, + lim_bk->min_sys_clk_div, + lim_bk->max_sys_clk_div, s, "op_sys_clk_div"); + if (!rval) + rval = bounds_check(dev, pll_bk->sys_clk_freq_hz, + lim_bk->min_sys_clk_freq_hz, + lim_bk->max_sys_clk_freq_hz, + s, "sys_clk_freq_hz"); if (!rval) - rval = bounds_check( - dev, pll->vt_bk.sys_clk_freq_hz, - lim->vt_bk.min_sys_clk_freq_hz, - lim->vt_bk.max_sys_clk_freq_hz, - "vt_sys_clk_freq_hz"); + rval = bounds_check(dev, pll_bk->sys_clk_div, + lim_bk->min_sys_clk_div, + lim_bk->max_sys_clk_div, + s, "sys_clk_div"); if (!rval) - rval = bounds_check( - dev, pll->vt_bk.pix_clk_freq_hz, - lim->vt_bk.min_pix_clk_freq_hz, - lim->vt_bk.max_pix_clk_freq_hz, - "vt_pix_clk_freq_hz"); + rval = bounds_check(dev, pll_bk->pix_clk_freq_hz, + lim_bk->min_pix_clk_freq_hz, + lim_bk->max_pix_clk_freq_hz, + s, "pix_clk_freq_hz"); + + return rval; +} +static int check_ext_bounds(struct device *dev, struct ccs_pll *pll) +{ 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"); @@ -201,7 +225,7 @@ static int check_all_bounds(struct device *dev, return -EINVAL; } - return rval; + return 0; } #define CPHY_CONST 7 @@ -610,11 +634,21 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, if (rval) continue; + rval = check_fr_bounds(dev, lim, pll, PLL_VT); + if (rval) + continue; + + rval = check_bk_bounds(dev, lim, pll, PLL_OP); + if (rval) + continue; + ccs_pll_calculate_vt(dev, lim, op_lim_bk, pll, op_pll_fr, op_pll_bk, cphy, phy_const); - rval = check_all_bounds(dev, lim, op_lim_fr, op_lim_bk, pll, - op_pll_fr, op_pll_bk); + rval = check_bk_bounds(dev, lim, pll, PLL_VT); + if (rval) + continue; + rval = check_ext_bounds(dev, pll); if (rval) continue; diff --git a/drivers/media/i2c/ccs-pll.h b/drivers/media/i2c/ccs-pll.h index 03c2428c76cd..6255803eee38 100644 --- a/drivers/media/i2c/ccs-pll.h +++ b/drivers/media/i2c/ccs-pll.h @@ -86,6 +86,7 @@ struct ccs_pll_branch_bk { * (input) * @vt_fr: Video timing front-end configuration (output) * @vt_bk: Video timing back-end configuration (output) + * @op_fr: Operational timing front-end configuration (output) * @op_bk: Operational timing back-end configuration (output) * @pixel_rate_csi: Pixel rate on the output data bus (output) * @pixel_rate_pixel_array: Nominal pixel rate in the sensor's pixel array @@ -112,6 +113,7 @@ struct ccs_pll { /* output values */ struct ccs_pll_branch_fr vt_fr; struct ccs_pll_branch_bk vt_bk; + struct ccs_pll_branch_fr op_fr; struct ccs_pll_branch_bk op_bk; uint32_t pixel_rate_csi; @@ -171,6 +173,7 @@ struct ccs_pll_branch_limits_bk { * @max_ext_clk_freq_hz: Maximum external clock frequency * @vt_fr: Video timing front-end limits * @vt_bk: Video timing back-end limits + * @op_fr: Operational timing front-end limits * @op_bk: Operational timing back-end limits * @min_line_length_pck_bin: Minimum line length in pixels, with binning * @min_line_length_pck: Minimum line length in pixels without binning @@ -182,6 +185,7 @@ struct ccs_pll_limits { struct ccs_pll_branch_limits_fr vt_fr; struct ccs_pll_branch_limits_bk vt_bk; + struct ccs_pll_branch_limits_fr op_fr; struct ccs_pll_branch_limits_bk op_bk; /* Other relevant limits */ From patchwork Wed Dec 2 18:06:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946627 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 04817C71155 for ; Wed, 2 Dec 2020 18:14:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A26C52224B for ; Wed, 2 Dec 2020 18:14:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389183AbgLBSOK (ORCPT ); Wed, 2 Dec 2020 13:14:10 -0500 Received: from retiisi.eu ([95.216.213.190]:33504 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2389072AbgLBSOJ (ORCPT ); Wed, 2 Dec 2020 13:14:09 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 2F091634CCD; Wed, 2 Dec 2020 20:08:33 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 29/38] ccs-pll: Make VT divisors 16-bit Date: Wed, 2 Dec 2020 20:06:32 +0200 Message-Id: <20201202180641.17401-30-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Make VT divisors 16-bit unsigned numbers. They don't need 32 bits after all. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 51 ++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index a6443589b948..7512f0313010 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -239,11 +239,11 @@ ccs_pll_calculate_vt(struct device *dev, const struct ccs_pll_limits *lim, struct ccs_pll_branch_bk *op_pll_bk, bool cphy, uint32_t phy_const) { - uint32_t sys_div; - uint32_t best_pix_div = INT_MAX >> 1; - uint32_t vt_op_binning_div; - uint32_t min_vt_div, max_vt_div, vt_div; - uint32_t min_sys_div, max_sys_div; + uint16_t sys_div; + uint16_t best_pix_div = SHRT_MAX >> 1; + uint16_t vt_op_binning_div; + uint16_t min_vt_div, max_vt_div, vt_div; + uint16_t min_sys_div, max_sys_div; if (pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) goto out_calc_pixel_rate; @@ -297,20 +297,19 @@ ccs_pll_calculate_vt(struct device *dev, const struct ccs_pll_limits *lim, /* Find smallest and biggest allowed vt divisor. */ dev_dbg(dev, "min_vt_div: %u\n", min_vt_div); - min_vt_div = max(min_vt_div, - DIV_ROUND_UP(pll_fr->pll_op_clk_freq_hz, - lim->vt_bk.max_pix_clk_freq_hz)); + min_vt_div = max_t(uint16_t, min_vt_div, + DIV_ROUND_UP(pll_fr->pll_op_clk_freq_hz, + lim->vt_bk.max_pix_clk_freq_hz)); dev_dbg(dev, "min_vt_div: max_vt_pix_clk_freq_hz: %u\n", min_vt_div); - min_vt_div = max_t(uint32_t, min_vt_div, - lim->vt_bk.min_pix_clk_div - * lim->vt_bk.min_sys_clk_div); + min_vt_div = max_t(uint16_t, min_vt_div, lim->vt_bk.min_pix_clk_div + * lim->vt_bk.min_sys_clk_div); dev_dbg(dev, "min_vt_div: min_vt_clk_div: %u\n", min_vt_div); max_vt_div = lim->vt_bk.max_sys_clk_div * lim->vt_bk.max_pix_clk_div; dev_dbg(dev, "max_vt_div: %u\n", max_vt_div); - max_vt_div = min(max_vt_div, - DIV_ROUND_UP(pll_fr->pll_op_clk_freq_hz, + max_vt_div = min_t(uint16_t, max_vt_div, + DIV_ROUND_UP(pll_fr->pll_op_clk_freq_hz, lim->vt_bk.min_pix_clk_freq_hz)); dev_dbg(dev, "max_vt_div: min_vt_pix_clk_freq_hz: %u\n", max_vt_div); @@ -321,26 +320,26 @@ ccs_pll_calculate_vt(struct device *dev, const struct ccs_pll_limits *lim, */ min_sys_div = lim->vt_bk.min_sys_clk_div; dev_dbg(dev, "min_sys_div: %u\n", min_sys_div); - min_sys_div = max(min_sys_div, - DIV_ROUND_UP(min_vt_div, - lim->vt_bk.max_pix_clk_div)); + min_sys_div = max_t(uint16_t, min_sys_div, + DIV_ROUND_UP(min_vt_div, + lim->vt_bk.max_pix_clk_div)); dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %u\n", min_sys_div); - min_sys_div = max(min_sys_div, - pll_fr->pll_op_clk_freq_hz - / lim->vt_bk.max_sys_clk_freq_hz); + min_sys_div = max_t(uint16_t, min_sys_div, + pll_fr->pll_op_clk_freq_hz + / lim->vt_bk.max_sys_clk_freq_hz); dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %u\n", min_sys_div); min_sys_div = clk_div_even_up(min_sys_div); dev_dbg(dev, "min_sys_div: one or even: %u\n", min_sys_div); max_sys_div = lim->vt_bk.max_sys_clk_div; dev_dbg(dev, "max_sys_div: %u\n", max_sys_div); - max_sys_div = min(max_sys_div, - DIV_ROUND_UP(max_vt_div, - lim->vt_bk.min_pix_clk_div)); + max_sys_div = min_t(uint16_t, max_sys_div, + DIV_ROUND_UP(max_vt_div, + lim->vt_bk.min_pix_clk_div)); dev_dbg(dev, "max_sys_div: min_vt_pix_clk_div: %u\n", max_sys_div); - max_sys_div = min(max_sys_div, - DIV_ROUND_UP(pll_fr->pll_op_clk_freq_hz, - lim->vt_bk.min_pix_clk_freq_hz)); + max_sys_div = min_t(uint16_t, max_sys_div, + DIV_ROUND_UP(pll_fr->pll_op_clk_freq_hz, + lim->vt_bk.min_pix_clk_freq_hz)); dev_dbg(dev, "max_sys_div: min_vt_pix_clk_freq_hz: %u\n", max_sys_div); /* @@ -376,7 +375,7 @@ ccs_pll_calculate_vt(struct device *dev, const struct ccs_pll_limits *lim, if (vt_div == rounded_div) break; } - if (best_pix_div < INT_MAX >> 1) + if (best_pix_div < SHRT_MAX >> 1) break; } From patchwork Wed Dec 2 18:06:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946631 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9D197C71155 for ; Wed, 2 Dec 2020 18:14:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4C73E221FC for ; Wed, 2 Dec 2020 18:14:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389367AbgLBSOZ (ORCPT ); Wed, 2 Dec 2020 13:14:25 -0500 Received: from retiisi.eu ([95.216.213.190]:33612 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2389271AbgLBSOZ (ORCPT ); Wed, 2 Dec 2020 13:14:25 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 41072634CCF; Wed, 2 Dec 2020 20:08:33 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 30/38] ccs-pll: Fix VT post-PLL divisor calculation Date: Wed, 2 Dec 2020 20:06:33 +0200 Message-Id: <20201202180641.17401-31-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The PLL calculator only searched even total divisor values apart from one, but this is wrong: the total divisor is odd in cases where system divisor is one. Fix this by including odd total PLL values where system divisor is one to the search. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index 7512f0313010..4321989b9013 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -347,14 +347,16 @@ ccs_pll_calculate_vt(struct device *dev, const struct ccs_pll_limits *lim, * into a value which is not smaller than div, the desired * divisor. */ - for (vt_div = min_vt_div; vt_div <= max_vt_div; - vt_div += 2 - (vt_div & 1)) { - for (sys_div = min_sys_div; - sys_div <= max_sys_div; + for (vt_div = min_vt_div; vt_div <= max_vt_div; vt_div++) { + uint16_t __max_sys_div = vt_div & 1 ? 1 : max_sys_div; + + for (sys_div = min_sys_div; sys_div <= __max_sys_div; sys_div += 2 - (sys_div & 1)) { - uint16_t pix_div = DIV_ROUND_UP(vt_div, sys_div); + uint16_t pix_div; uint16_t rounded_div; + pix_div = DIV_ROUND_UP(vt_div, sys_div); + if (pix_div < lim->vt_bk.min_pix_clk_div || pix_div > lim->vt_bk.max_pix_clk_div) { dev_dbg(dev, From patchwork Wed Dec 2 18:06:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946633 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CA201C8300F for ; Wed, 2 Dec 2020 18:14:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7C48D205F4 for ; Wed, 2 Dec 2020 18:14:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389371AbgLBSO1 (ORCPT ); Wed, 2 Dec 2020 13:14:27 -0500 Received: from retiisi.eu ([95.216.213.190]:33622 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2389365AbgLBSO1 (ORCPT ); Wed, 2 Dec 2020 13:14:27 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 46624634CD0; Wed, 2 Dec 2020 20:08:33 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 31/38] ccs-pll: Separate VT divisor limit calculation from the rest Date: Wed, 2 Dec 2020 20:06:34 +0200 Message-Id: <20201202180641.17401-32-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Separate VT divisor limit calculation from the rest of the VT PLL branch calculation. This way it can be used for dual PLL support as well. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 64 +++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index 4321989b9013..8b300e786451 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -228,6 +228,41 @@ static int check_ext_bounds(struct device *dev, struct ccs_pll *pll) return 0; } +static void +ccs_pll_find_vt_sys_div(struct device *dev, const struct ccs_pll_limits *lim, + struct ccs_pll *pll, struct ccs_pll_branch_fr *pll_fr, + uint16_t min_vt_div, uint16_t max_vt_div, + uint16_t *min_sys_div, uint16_t *max_sys_div) +{ + /* + * Find limits for sys_clk_div. Not all values are possible with all + * values of pix_clk_div. + */ + *min_sys_div = lim->vt_bk.min_sys_clk_div; + dev_dbg(dev, "min_sys_div: %u\n", *min_sys_div); + *min_sys_div = max_t(uint16_t, *min_sys_div, + DIV_ROUND_UP(min_vt_div, + lim->vt_bk.max_pix_clk_div)); + dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %u\n", *min_sys_div); + *min_sys_div = max_t(uint16_t, *min_sys_div, + pll_fr->pll_op_clk_freq_hz + / lim->vt_bk.max_sys_clk_freq_hz); + dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %u\n", *min_sys_div); + *min_sys_div = clk_div_even_up(*min_sys_div); + dev_dbg(dev, "min_sys_div: one or even: %u\n", *min_sys_div); + + *max_sys_div = lim->vt_bk.max_sys_clk_div; + dev_dbg(dev, "max_sys_div: %u\n", *max_sys_div); + *max_sys_div = min_t(uint16_t, *max_sys_div, + DIV_ROUND_UP(max_vt_div, + lim->vt_bk.min_pix_clk_div)); + dev_dbg(dev, "max_sys_div: min_vt_pix_clk_div: %u\n", *max_sys_div); + *max_sys_div = min_t(uint16_t, *max_sys_div, + DIV_ROUND_UP(pll_fr->pll_op_clk_freq_hz, + lim->vt_bk.min_pix_clk_freq_hz)); + dev_dbg(dev, "max_sys_div: min_vt_pix_clk_freq_hz: %u\n", *max_sys_div); +} + #define CPHY_CONST 7 #define DPHY_CONST 16 #define PHY_CONST_DIV 16 @@ -314,33 +349,8 @@ ccs_pll_calculate_vt(struct device *dev, const struct ccs_pll_limits *lim, dev_dbg(dev, "max_vt_div: min_vt_pix_clk_freq_hz: %u\n", max_vt_div); - /* - * Find limitsits for sys_clk_div. Not all values are possible - * with all values of pix_clk_div. - */ - min_sys_div = lim->vt_bk.min_sys_clk_div; - dev_dbg(dev, "min_sys_div: %u\n", min_sys_div); - min_sys_div = max_t(uint16_t, min_sys_div, - DIV_ROUND_UP(min_vt_div, - lim->vt_bk.max_pix_clk_div)); - dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %u\n", min_sys_div); - min_sys_div = max_t(uint16_t, min_sys_div, - pll_fr->pll_op_clk_freq_hz - / lim->vt_bk.max_sys_clk_freq_hz); - dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %u\n", min_sys_div); - min_sys_div = clk_div_even_up(min_sys_div); - dev_dbg(dev, "min_sys_div: one or even: %u\n", min_sys_div); - - max_sys_div = lim->vt_bk.max_sys_clk_div; - dev_dbg(dev, "max_sys_div: %u\n", max_sys_div); - max_sys_div = min_t(uint16_t, max_sys_div, - DIV_ROUND_UP(max_vt_div, - lim->vt_bk.min_pix_clk_div)); - dev_dbg(dev, "max_sys_div: min_vt_pix_clk_div: %u\n", max_sys_div); - max_sys_div = min_t(uint16_t, max_sys_div, - DIV_ROUND_UP(pll_fr->pll_op_clk_freq_hz, - lim->vt_bk.min_pix_clk_freq_hz)); - dev_dbg(dev, "max_sys_div: min_vt_pix_clk_freq_hz: %u\n", max_sys_div); + ccs_pll_find_vt_sys_div(dev, lim, pll, pll_fr, min_vt_div, + max_vt_div, &min_sys_div, &max_sys_div); /* * Find pix_div such that a legal pix_div * sys_div results From patchwork Wed Dec 2 18:06:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946635 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F37FBC71156 for ; Wed, 2 Dec 2020 18:14:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AB37A206D5 for ; Wed, 2 Dec 2020 18:14:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389370AbgLBSO1 (ORCPT ); Wed, 2 Dec 2020 13:14:27 -0500 Received: from retiisi.eu ([95.216.213.190]:33618 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2389366AbgLBSO1 (ORCPT ); Wed, 2 Dec 2020 13:14:27 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 567CE634CD1; Wed, 2 Dec 2020 20:08:33 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 32/38] ccs-pll: Add trivial dual PLL support Date: Wed, 2 Dec 2020 20:06:35 +0200 Message-Id: <20201202180641.17401-33-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add support for sensors that have separate VT and OP domain PLLs. This support is trivial in the sense that it aims for the same VT pixel rate than that on the CSI-2 bus. The vast majority of sensors is better supported by higher frequencies in VT domain in binned and possibly scaled configurations. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 217 ++++++++++++++++++++++++++++++++---- drivers/media/i2c/ccs-pll.h | 1 + 2 files changed, 196 insertions(+), 22 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index 8b300e786451..91b578a05a98 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -92,7 +92,8 @@ static void print_pll(struct device *dev, struct ccs_pll *pll) for (i = 0, br = branches; i < ARRAY_SIZE(branches); i++, br++) { const char *s = pll_string(br->which); - if (br->which == PLL_VT) { + if (pll->flags & CCS_PLL_FLAG_DUAL_PLL || + br->which == PLL_VT) { dev_dbg(dev, "%s_pre_pll_clk_div\t\t%u\n", s, br->fr->pre_pll_clk_div); dev_dbg(dev, "%s_pll_multiplier\t\t%u\n", s, @@ -118,7 +119,7 @@ static void print_pll(struct device *dev, struct ccs_pll *pll) } } - dev_dbg(dev, "flags%s%s%s%s%s%s\n", + dev_dbg(dev, "flags%s%s%s%s%s%s%s\n", pll->flags & PLL_FL(LANE_SPEED_MODEL) ? " lane-speed" : "", pll->flags & PLL_FL(LINK_DECOUPLED) ? " link-decoupled" : "", pll->flags & PLL_FL(EXT_IP_PLL_DIVIDER) ? @@ -126,7 +127,8 @@ static void print_pll(struct device *dev, struct ccs_pll *pll) pll->flags & PLL_FL(FLEXIBLE_OP_PIX_CLK_DIV) ? " flexible-op-pix-div" : "", pll->flags & PLL_FL(FIFO_DERATING) ? " fifo-derating" : "", - pll->flags & PLL_FL(FIFO_OVERRATING) ? " fifo-overrating" : ""); + pll->flags & PLL_FL(FIFO_OVERRATING) ? " fifo-overrating" : "", + pll->flags & PLL_FL(DUAL_PLL) ? " dual-pll" : ""); } static int check_fr_bounds(struct device *dev, @@ -267,6 +269,152 @@ ccs_pll_find_vt_sys_div(struct device *dev, const struct ccs_pll_limits *lim, #define DPHY_CONST 16 #define PHY_CONST_DIV 16 +static inline int +__ccs_pll_calculate_vt_tree(struct device *dev, + const struct ccs_pll_limits *lim, + struct ccs_pll *pll, uint32_t mul, uint32_t div) +{ + const struct ccs_pll_branch_limits_fr *lim_fr = &lim->vt_fr; + const struct ccs_pll_branch_limits_bk *lim_bk = &lim->vt_bk; + struct ccs_pll_branch_fr *pll_fr = &pll->vt_fr; + struct ccs_pll_branch_bk *pll_bk = &pll->vt_bk; + uint32_t more_mul; + uint16_t best_pix_div = SHRT_MAX >> 1, best_div; + uint16_t vt_div, min_sys_div, max_sys_div, sys_div; + + pll_fr->pll_ip_clk_freq_hz = + pll->ext_clk_freq_hz / pll_fr->pre_pll_clk_div; + + dev_dbg(dev, "vt_pll_ip_clk_freq_hz %u\n", pll_fr->pll_ip_clk_freq_hz); + + more_mul = one_or_more(DIV_ROUND_UP(lim_fr->min_pll_op_clk_freq_hz, + pll_fr->pll_ip_clk_freq_hz * mul)); + + dev_dbg(dev, "more_mul: %u\n", more_mul); + more_mul *= DIV_ROUND_UP(lim_fr->min_pll_multiplier, mul * more_mul); + dev_dbg(dev, "more_mul2: %u\n", more_mul); + + pll_fr->pll_multiplier = mul * more_mul; + + if (pll_fr->pll_multiplier * pll_fr->pll_ip_clk_freq_hz > + lim_fr->max_pll_op_clk_freq_hz) + return -EINVAL; + + pll_fr->pll_op_clk_freq_hz = + pll_fr->pll_ip_clk_freq_hz * pll_fr->pll_multiplier; + + vt_div = div * more_mul; + + ccs_pll_find_vt_sys_div(dev, lim, pll, pll_fr, vt_div, vt_div, + &min_sys_div, &max_sys_div); + + max_sys_div = (vt_div & 1) ? 1 : max_sys_div; + + dev_dbg(dev, "vt min/max_sys_div: %u,%u\n", min_sys_div, max_sys_div); + + for (sys_div = min_sys_div; sys_div <= max_sys_div; + sys_div += 2 - (sys_div & 1)) { + uint16_t pix_div; + + if (vt_div % sys_div) + continue; + + pix_div = vt_div / sys_div; + + if (pix_div < lim_bk->min_pix_clk_div || + pix_div > lim_bk->max_pix_clk_div) { + dev_dbg(dev, + "pix_div %u too small or too big (%u--%u)\n", + pix_div, + lim_bk->min_pix_clk_div, + lim_bk->max_pix_clk_div); + continue; + } + + if (pix_div * sys_div <= best_div) { + best_pix_div = pix_div; + best_div = pix_div * sys_div; + } + } + if (best_pix_div == SHRT_MAX >> 1) + return -EINVAL; + + pll_bk->sys_clk_div = best_div / best_pix_div; + pll_bk->pix_clk_div = best_pix_div; + + pll_bk->sys_clk_freq_hz = + pll_fr->pll_op_clk_freq_hz / pll_bk->sys_clk_div; + pll_bk->pix_clk_freq_hz = + pll_bk->sys_clk_freq_hz / pll_bk->pix_clk_div; + + pll->pixel_rate_pixel_array = + pll_bk->pix_clk_freq_hz * pll->vt_lanes; + + return 0; +} + +static int ccs_pll_calculate_vt_tree(struct device *dev, + const struct ccs_pll_limits *lim, + struct ccs_pll *pll) +{ + const struct ccs_pll_branch_limits_fr *lim_fr = &lim->vt_fr; + struct ccs_pll_branch_fr *pll_fr = &pll->vt_fr; + uint16_t min_pre_pll_clk_div = lim_fr->min_pre_pll_clk_div; + uint16_t max_pre_pll_clk_div = lim_fr->max_pre_pll_clk_div; + uint32_t pre_mul, pre_div; + + pre_div = gcd(pll->pixel_rate_csi, + pll->ext_clk_freq_hz * pll->vt_lanes); + pre_mul = pll->pixel_rate_csi / pre_div; + pre_div = pll->ext_clk_freq_hz * pll->vt_lanes / pre_div; + + /* Make sure PLL input frequency is within limits */ + max_pre_pll_clk_div = + min_t(uint16_t, max_pre_pll_clk_div, + DIV_ROUND_UP(pll->ext_clk_freq_hz, + lim_fr->min_pll_ip_clk_freq_hz)); + + min_pre_pll_clk_div = max_t(uint16_t, min_pre_pll_clk_div, + pll->ext_clk_freq_hz / + lim_fr->max_pll_ip_clk_freq_hz); + + dev_dbg(dev, "vt min/max_pre_pll_clk_div: %u,%u\n", + min_pre_pll_clk_div, max_pre_pll_clk_div); + + for (pll_fr->pre_pll_clk_div = min_pre_pll_clk_div; + pll_fr->pre_pll_clk_div <= max_pre_pll_clk_div; + pll_fr->pre_pll_clk_div += + (pll->flags & CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER) ? 1 : + 2 - (pll_fr->pre_pll_clk_div & 1)) { + uint32_t mul, div; + int rval; + + div = gcd(pre_mul * pll_fr->pre_pll_clk_div, pre_div); + mul = pre_mul * pll_fr->pre_pll_clk_div / div; + div = pre_div / div; + + dev_dbg(dev, "vt pre-div/mul/div: %u,%u,%u\n", + pll_fr->pre_pll_clk_div, mul, div); + + rval = __ccs_pll_calculate_vt_tree(dev, lim, pll, + mul, div); + if (rval) + continue; + + rval = check_fr_bounds(dev, lim, pll, PLL_VT); + if (rval) + continue; + + rval = check_bk_bounds(dev, lim, pll, PLL_VT); + if (rval) + continue; + + return 0; + } + + return -EINVAL; +} + static void ccs_pll_calculate_vt(struct device *dev, const struct ccs_pll_limits *lim, const struct ccs_pll_branch_limits_bk *op_lim_bk, @@ -525,10 +673,10 @@ ccs_pll_calculate_op(struct device *dev, const struct ccs_pll_limits *lim, int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, struct ccs_pll *pll) { - const struct ccs_pll_branch_limits_fr *op_lim_fr = &lim->vt_fr; - const struct ccs_pll_branch_limits_bk *op_lim_bk = &lim->op_bk; - struct ccs_pll_branch_fr *op_pll_fr = &pll->vt_fr; - struct ccs_pll_branch_bk *op_pll_bk = &pll->op_bk; + const struct ccs_pll_branch_limits_fr *op_lim_fr; + const struct ccs_pll_branch_limits_bk *op_lim_bk; + struct ccs_pll_branch_fr *op_pll_fr; + struct ccs_pll_branch_bk *op_pll_bk; bool cphy = pll->bus_type == CCS_PLL_BUS_TYPE_CSI2_CPHY; uint32_t phy_const = cphy ? CPHY_CONST : DPHY_CONST; uint16_t min_op_pre_pll_clk_div; @@ -544,6 +692,28 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, pll->vt_lanes = 1; } + if (pll->flags & CCS_PLL_FLAG_DUAL_PLL) { + op_lim_fr = &lim->op_fr; + op_lim_bk = &lim->op_bk; + op_pll_fr = &pll->op_fr; + op_pll_bk = &pll->op_bk; + } else if (pll->flags & CCS_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_lim_fr = &lim->vt_fr; + op_lim_bk = &lim->vt_bk; + op_pll_fr = &pll->vt_fr; + op_pll_bk = &pll->vt_bk; + } else { + op_lim_fr = &lim->vt_fr; + op_lim_bk = &lim->op_bk; + op_pll_fr = &pll->vt_fr; + op_pll_bk = &pll->op_bk; + } + if (!pll->op_lanes || !pll->vt_lanes || !pll->bits_per_pixel || !pll->ext_clk_freq_hz || !pll->link_freq || !pll->scale_m || !op_lim_fr->min_pll_ip_clk_freq_hz || @@ -567,17 +737,6 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, 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 - * instead. The OP values are ignored for the rest of - * the PLL calculation. - */ - op_lim_fr = &lim->vt_fr; - op_lim_bk = &lim->vt_bk; - op_pll_bk = &pll->vt_bk; - } - dev_dbg(dev, "binning: %ux%u\n", pll->binning_horizontal, pll->binning_vertical); @@ -653,6 +812,9 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, if (rval) continue; + if (pll->flags & CCS_PLL_FLAG_DUAL_PLL) + break; + ccs_pll_calculate_vt(dev, lim, op_lim_bk, pll, op_pll_fr, op_pll_bk, cphy, phy_const); @@ -663,14 +825,25 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, if (rval) continue; - print_pll(dev, pll); + break; + } + + if (rval) { + dev_dbg(dev, "unable to compute pre_pll divisor\n"); - return 0; + return rval; } - dev_dbg(dev, "unable to compute pre_pll divisor\n"); + if (pll->flags & CCS_PLL_FLAG_DUAL_PLL) { + rval = ccs_pll_calculate_vt_tree(dev, lim, pll); - return rval; + if (rval) + return rval; + } + + print_pll(dev, pll); + + return 0; } EXPORT_SYMBOL_GPL(ccs_pll_calculate); diff --git a/drivers/media/i2c/ccs-pll.h b/drivers/media/i2c/ccs-pll.h index 6255803eee38..517ee504f44a 100644 --- a/drivers/media/i2c/ccs-pll.h +++ b/drivers/media/i2c/ccs-pll.h @@ -29,6 +29,7 @@ #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) +#define CCS_PLL_FLAG_DUAL_PLL BIT(8) /** * struct ccs_pll_branch_fr - CCS PLL configuration (front) From patchwork Wed Dec 2 18:06:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946637 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 73F3AC83013 for ; Wed, 2 Dec 2020 18:14:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1B5F0206D5 for ; Wed, 2 Dec 2020 18:14:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389372AbgLBSO2 (ORCPT ); Wed, 2 Dec 2020 13:14:28 -0500 Received: from retiisi.eu ([95.216.213.190]:33624 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2389271AbgLBSO2 (ORCPT ); Wed, 2 Dec 2020 13:14:28 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 69179634CD2; Wed, 2 Dec 2020 20:08:33 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 33/38] ccs: Dual PLL support Date: Wed, 2 Dec 2020 20:06:36 +0200 Message-Id: <20201202180641.17401-34-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add support for sensors that either require dual PLL or support single or dual PLL but use dual PLL as default. Use sensor default configuration for sensors that support both modes. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 9 +++++-- drivers/media/i2c/ccs/ccs-core.c | 45 +++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index 91b578a05a98..7df7b96e78e6 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -331,7 +331,10 @@ __ccs_pll_calculate_vt_tree(struct device *dev, continue; } - if (pix_div * sys_div <= best_div) { + dev_dbg(dev, "sys/pix/best_pix: %u,%u,%u\n", sys_div, pix_div, + best_pix_div); + + if (pix_div * sys_div <= best_pix_div) { best_pix_div = pix_div; best_div = pix_div * sys_div; } @@ -804,7 +807,9 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, if (rval) continue; - rval = check_fr_bounds(dev, lim, pll, PLL_VT); + rval = check_fr_bounds(dev, lim, pll, + pll->flags & CCS_PLL_FLAG_DUAL_PLL ? + PLL_OP : PLL_VT); if (rval) continue; diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index 849c1001e3cc..137d951b551a 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -396,7 +396,23 @@ static int ccs_pll_configure(struct ccs_sensor *sensor) if (rval < 0) return rval; - return ccs_write(sensor, OP_SYS_CLK_DIV, pll->op_bk.sys_clk_div); + rval = ccs_write(sensor, OP_SYS_CLK_DIV, pll->op_bk.sys_clk_div); + if (rval < 0) + return rval; + + if (!(pll->flags & CCS_PLL_FLAG_DUAL_PLL)) + return 0; + + rval = ccs_write(sensor, PLL_MODE, CCS_PLL_MODE_DUAL); + if (rval < 0) + return rval; + + rval = ccs_write(sensor, OP_PRE_PLL_CLK_DIV, + pll->op_fr.pre_pll_clk_div); + if (rval < 0) + return rval; + + return ccs_write(sensor, OP_PLL_MULTIPLIER, pll->op_fr.pll_multiplier); } static int ccs_pll_try(struct ccs_sensor *sensor, struct ccs_pll *pll) @@ -413,6 +429,16 @@ static int ccs_pll_try(struct ccs_sensor *sensor, struct ccs_pll *pll) .min_pll_op_clk_freq_hz = CCS_LIM(sensor, MIN_PLL_OP_CLK_FREQ_MHZ), .max_pll_op_clk_freq_hz = CCS_LIM(sensor, MAX_PLL_OP_CLK_FREQ_MHZ), }, + .op_fr = { + .min_pre_pll_clk_div = CCS_LIM(sensor, MIN_OP_PRE_PLL_CLK_DIV), + .max_pre_pll_clk_div = CCS_LIM(sensor, MAX_OP_PRE_PLL_CLK_DIV), + .min_pll_ip_clk_freq_hz = CCS_LIM(sensor, MIN_OP_PLL_IP_CLK_FREQ_MHZ), + .max_pll_ip_clk_freq_hz = CCS_LIM(sensor, MAX_OP_PLL_IP_CLK_FREQ_MHZ), + .min_pll_multiplier = CCS_LIM(sensor, MIN_OP_PLL_MULTIPLIER), + .max_pll_multiplier = CCS_LIM(sensor, MAX_OP_PLL_MULTIPLIER), + .min_pll_op_clk_freq_hz = CCS_LIM(sensor, MIN_OP_PLL_OP_CLK_FREQ_MHZ), + .max_pll_op_clk_freq_hz = CCS_LIM(sensor, MAX_OP_PLL_OP_CLK_FREQ_MHZ), + }, .op_bk = { .min_sys_clk_div = CCS_LIM(sensor, MIN_OP_SYS_CLK_DIV), .max_sys_clk_div = CCS_LIM(sensor, MAX_OP_SYS_CLK_DIV), @@ -3232,6 +3258,23 @@ static int ccs_probe(struct i2c_client *client) CCS_FIFO_SUPPORT_CAPABILITY_DERATING_OVERRATING) sensor->pll.flags |= CCS_PLL_FLAG_FIFO_DERATING | CCS_PLL_FLAG_FIFO_OVERRATING; + if (CCS_LIM(sensor, CLOCK_TREE_PLL_CAPABILITY) & + CCS_CLOCK_TREE_PLL_CAPABILITY_DUAL_PLL) { + if (CCS_LIM(sensor, CLOCK_TREE_PLL_CAPABILITY) & + CCS_CLOCK_TREE_PLL_CAPABILITY_SINGLE_PLL) { + u32 v; + + /* Use sensor default in PLL mode selection */ + rval = ccs_read(sensor, PLL_MODE, &v); + if (rval) + goto out_cleanup; + + if (v == CCS_PLL_MODE_DUAL) + sensor->pll.flags |= CCS_PLL_FLAG_DUAL_PLL; + } else { + sensor->pll.flags |= CCS_PLL_FLAG_DUAL_PLL; + } + } 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); From patchwork Wed Dec 2 18:06:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946639 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1B2D7C83014 for ; Wed, 2 Dec 2020 18:14:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DA62F205F4 for ; Wed, 2 Dec 2020 18:14:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389373AbgLBSO2 (ORCPT ); Wed, 2 Dec 2020 13:14:28 -0500 Received: from retiisi.eu ([95.216.213.190]:33628 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2389368AbgLBSO2 (ORCPT ); Wed, 2 Dec 2020 13:14:28 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 79D98634CD4; Wed, 2 Dec 2020 20:08:33 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 34/38] ccs-pll: Add support for DDR OP system and pixel clocks Date: Wed, 2 Dec 2020 20:06:37 +0200 Message-Id: <20201202180641.17401-35-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add support for dual data rate operational system and pixel clocks. This is implemented using two PLL flags. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 64 +++++++++++++++++++++++++------------ drivers/media/i2c/ccs-pll.h | 2 ++ 2 files changed, 46 insertions(+), 20 deletions(-) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index 7df7b96e78e6..5a0162347777 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -119,7 +119,7 @@ static void print_pll(struct device *dev, struct ccs_pll *pll) } } - dev_dbg(dev, "flags%s%s%s%s%s%s%s\n", + dev_dbg(dev, "flags%s%s%s%s%s%s%s%s%s\n", pll->flags & PLL_FL(LANE_SPEED_MODEL) ? " lane-speed" : "", pll->flags & PLL_FL(LINK_DECOUPLED) ? " link-decoupled" : "", pll->flags & PLL_FL(EXT_IP_PLL_DIVIDER) ? @@ -128,7 +128,19 @@ static void print_pll(struct device *dev, struct ccs_pll *pll) " flexible-op-pix-div" : "", pll->flags & PLL_FL(FIFO_DERATING) ? " fifo-derating" : "", pll->flags & PLL_FL(FIFO_OVERRATING) ? " fifo-overrating" : "", - pll->flags & PLL_FL(DUAL_PLL) ? " dual-pll" : ""); + pll->flags & PLL_FL(DUAL_PLL) ? " dual-pll" : "", + pll->flags & PLL_FL(OP_SYS_DDR) ? " op-sys-ddr" : "", + pll->flags & PLL_FL(OP_PIX_DDR) ? " op-pix-ddr" : ""); +} + +static uint32_t op_sys_ddr(uint32_t flags) +{ + return flags & CCS_PLL_FLAG_OP_SYS_DDR ? 1 : 0; +} + +static uint32_t op_pix_ddr(uint32_t flags) +{ + return flags & CCS_PLL_FLAG_OP_PIX_DDR ? 1 : 0; } static int check_fr_bounds(struct device *dev, @@ -441,8 +453,8 @@ ccs_pll_calculate_vt(struct device *dev, const struct ccs_pll_limits *lim, 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; + * pll->vt_lanes * phy_const / pll->op_lanes + / (PHY_CONST_DIV << op_pix_ddr(pll->flags)); } else { /* * Some sensors perform analogue binning and some do this @@ -478,7 +490,7 @@ ccs_pll_calculate_vt(struct device *dev, const struct ccs_pll_limits *lim, CCS_PLL_FLAG_LANE_SPEED_MODEL ? pll->csi2.lanes : 1) * vt_op_binning_div * pll->scale_m - * PHY_CONST_DIV); + * PHY_CONST_DIV << op_pix_ddr(pll->flags)); } /* Find smallest and biggest allowed vt divisor. */ @@ -572,7 +584,8 @@ ccs_pll_calculate_op(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 l, bool cphy, uint32_t phy_const) + uint32_t div, uint32_t op_sys_clk_freq_hz_sdr, uint32_t l, + bool cphy, uint32_t phy_const) { /* * Higher multipliers (and divisors) are often required than @@ -658,15 +671,22 @@ ccs_pll_calculate_op(struct device *dev, const struct ccs_pll_limits *lim, * op_pll_fr->pll_multiplier; if (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL) - op_pll_bk->pix_clk_div = pll->bits_per_pixel - * pll->op_lanes * phy_const - / PHY_CONST_DIV / pll->csi2.lanes / l; + op_pll_bk->pix_clk_div = + (pll->bits_per_pixel + * pll->op_lanes * (phy_const << op_sys_ddr(pll->flags)) + / PHY_CONST_DIV / pll->csi2.lanes / l) + >> op_pix_ddr(pll->flags); else op_pll_bk->pix_clk_div = - pll->bits_per_pixel * phy_const / PHY_CONST_DIV / l; + (pll->bits_per_pixel + * (phy_const << op_sys_ddr(pll->flags)) + / PHY_CONST_DIV / l) >> op_pix_ddr(pll->flags); op_pll_bk->pix_clk_freq_hz = - op_pll_bk->sys_clk_freq_hz / op_pll_bk->pix_clk_div; + (op_sys_clk_freq_hz_sdr >> op_pix_ddr(pll->flags)) + / op_pll_bk->pix_clk_div; + op_pll_bk->sys_clk_freq_hz = + op_sys_clk_freq_hz_sdr >> op_sys_ddr(pll->flags); dev_dbg(dev, "op_pix_clk_div: %u\n", op_pll_bk->pix_clk_div); @@ -682,6 +702,7 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, struct ccs_pll_branch_bk *op_pll_bk; bool cphy = pll->bus_type == CCS_PLL_BUS_TYPE_CSI2_CPHY; uint32_t phy_const = cphy ? CPHY_CONST : DPHY_CONST; + uint32_t op_sys_clk_freq_hz_sdr; uint16_t min_op_pre_pll_clk_div; uint16_t max_op_pre_pll_clk_div; uint32_t mul, div; @@ -731,7 +752,8 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, * op_pix_clk_div is supported */ if (!(pll->flags & CCS_PLL_FLAG_FLEXIBLE_OP_PIX_CLK_DIV) && - (pll->bits_per_pixel * pll->op_lanes) % (pll->csi2.lanes * l)) { + (pll->bits_per_pixel * pll->op_lanes) % + (pll->csi2.lanes * l << op_pix_ddr(pll->flags))) { dev_dbg(dev, "op_pix_clk_div not an integer (bpp %u, op lanes %u, lanes %u, l %u)\n", pll->bits_per_pixel, pll->op_lanes, pll->csi2.lanes, l); return -EINVAL; @@ -746,12 +768,12 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, switch (pll->bus_type) { 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 + op_sys_clk_freq_hz_sdr = pll->link_freq * 2 * (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ? 1 : pll->csi2.lanes); break; case CCS_PLL_BUS_TYPE_CSI2_CPHY: - op_pll_bk->sys_clk_freq_hz = + op_sys_clk_freq_hz_sdr = pll->link_freq * (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ? 1 : pll->csi2.lanes); @@ -761,7 +783,7 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, } pll->pixel_rate_csi = - div_u64((uint64_t)op_pll_bk->sys_clk_freq_hz + div_u64((uint64_t)op_sys_clk_freq_hz_sdr * (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ? pll->csi2.lanes : 1) * PHY_CONST_DIV, phy_const * pll->bits_per_pixel * l); @@ -781,9 +803,10 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, dev_dbg(dev, "pre-pll check: min / max op_pre_pll_clk_div: %u / %u\n", min_op_pre_pll_clk_div, max_op_pre_pll_clk_div); - i = gcd(op_pll_bk->sys_clk_freq_hz, pll->ext_clk_freq_hz); - mul = op_pll_bk->sys_clk_freq_hz / i; - div = pll->ext_clk_freq_hz / i; + i = gcd(op_sys_clk_freq_hz_sdr, + pll->ext_clk_freq_hz << op_pix_ddr(pll->flags)); + mul = op_sys_clk_freq_hz_sdr / i; + div = (pll->ext_clk_freq_hz << op_pix_ddr(pll->flags)) / i; dev_dbg(dev, "mul %u / div %u\n", mul, div); min_op_pre_pll_clk_div = @@ -802,8 +825,9 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim, (pll->flags & CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER) ? 1 : 2 - (op_pll_fr->pre_pll_clk_div & 1)) { rval = ccs_pll_calculate_op(dev, lim, op_lim_fr, op_lim_bk, pll, - op_pll_fr, op_pll_bk, mul, div, l, - cphy, phy_const); + op_pll_fr, op_pll_bk, mul, div, + op_sys_clk_freq_hz_sdr, l, cphy, + phy_const); if (rval) continue; diff --git a/drivers/media/i2c/ccs-pll.h b/drivers/media/i2c/ccs-pll.h index 517ee504f44a..b97d7ff50ea5 100644 --- a/drivers/media/i2c/ccs-pll.h +++ b/drivers/media/i2c/ccs-pll.h @@ -30,6 +30,8 @@ #define CCS_PLL_FLAG_FIFO_DERATING BIT(6) #define CCS_PLL_FLAG_FIFO_OVERRATING BIT(7) #define CCS_PLL_FLAG_DUAL_PLL BIT(8) +#define CCS_PLL_FLAG_OP_SYS_DDR BIT(9) +#define CCS_PLL_FLAG_OP_PIX_DDR BIT(10) /** * struct ccs_pll_branch_fr - CCS PLL configuration (front) From patchwork Wed Dec 2 18:06:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946641 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3B620C71156 for ; Wed, 2 Dec 2020 18:15:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DC6E6206D5 for ; Wed, 2 Dec 2020 18:15:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387793AbgLBSPY (ORCPT ); Wed, 2 Dec 2020 13:15:24 -0500 Received: from retiisi.eu ([95.216.213.190]:33494 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728928AbgLBSPY (ORCPT ); Wed, 2 Dec 2020 13:15:24 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 8C960634CD5; Wed, 2 Dec 2020 20:08:33 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 35/38] ccs: Add support for DDR OP SYS and OP PIX clocks Date: Wed, 2 Dec 2020 20:06:38 +0200 Message-Id: <20201202180641.17401-36-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Support dual data rate operational system and pixel clocks by conveying the flags to the PLL calculator and updating how the link rate is calculated. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs/ccs-core.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index 137d951b551a..c41c47b40e73 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -388,7 +388,8 @@ static int ccs_pll_configure(struct ccs_sensor *sensor) DIV_ROUND_UP(pll->op_bk.sys_clk_freq_hz, 1000000 / 256 / 256) * (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ? - sensor->pll.csi2.lanes : 1)); + sensor->pll.csi2.lanes : 1) << + (pll->flags & CCS_PLL_FLAG_OP_SYS_DDR ? 1 : 0)); if (rval < 0 || sensor->pll.flags & CCS_PLL_FLAG_NO_OP_CLOCKS) return rval; @@ -3274,6 +3275,12 @@ static int ccs_probe(struct i2c_client *client) } else { sensor->pll.flags |= CCS_PLL_FLAG_DUAL_PLL; } + if (CCS_LIM(sensor, CLOCK_CALCULATION) & + CCS_CLOCK_CALCULATION_DUAL_PLL_OP_SYS_DDR) + sensor->pll.flags |= CCS_PLL_FLAG_OP_SYS_DDR; + if (CCS_LIM(sensor, CLOCK_CALCULATION) & + CCS_CLOCK_CALCULATION_DUAL_PLL_OP_PIX_DDR) + sensor->pll.flags |= CCS_PLL_FLAG_OP_PIX_DDR; } sensor->pll.op_bits_per_lane = CCS_LIM(sensor, OP_BITS_PER_LANE); sensor->pll.ext_clk_freq_hz = sensor->hwcfg.ext_clk; From patchwork Wed Dec 2 18:06:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946647 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 75000C71155 for ; Wed, 2 Dec 2020 18:15:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1831C221FC for ; Wed, 2 Dec 2020 18:15:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389386AbgLBSP0 (ORCPT ); Wed, 2 Dec 2020 13:15:26 -0500 Received: from retiisi.eu ([95.216.213.190]:33498 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2389264AbgLBSP0 (ORCPT ); Wed, 2 Dec 2020 13:15:26 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id 9FB65634CD7; Wed, 2 Dec 2020 20:08:33 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 36/38] ccs: Print written register values Date: Wed, 2 Dec 2020 20:06:39 +0200 Message-Id: <20201202180641.17401-37-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org This helps debugging register writes. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs/ccs-reg-access.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/i2c/ccs/ccs-reg-access.c b/drivers/media/i2c/ccs/ccs-reg-access.c index 3de863e3bf26..b776af2a3c33 100644 --- a/drivers/media/i2c/ccs/ccs-reg-access.c +++ b/drivers/media/i2c/ccs/ccs-reg-access.c @@ -338,6 +338,10 @@ int ccs_write_addr_no_quirk(struct ccs_sensor *sensor, u32 reg, u32 val) put_unaligned_be16(CCS_REG_ADDR(reg), data); put_unaligned_be32(val << (8 * (sizeof(val) - len)), data + 2); + dev_dbg(&client->dev, "writing reg 0x%4.4x value 0x%*.*x (%u)\n", + CCS_REG_ADDR(reg), ccs_reg_width(reg) << 1, + ccs_reg_width(reg) << 1, val, val); + r = ccs_write_retry(client, &msg); if (r) dev_err(&client->dev, From patchwork Wed Dec 2 18:06:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946643 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id ABBC1C8300F for ; Wed, 2 Dec 2020 18:15:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4F2B1205F4 for ; Wed, 2 Dec 2020 18:15:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389298AbgLBSP0 (ORCPT ); Wed, 2 Dec 2020 13:15:26 -0500 Received: from retiisi.eu ([95.216.213.190]:33496 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2389384AbgLBSP0 (ORCPT ); Wed, 2 Dec 2020 13:15:26 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id B3D2F634CD8; Wed, 2 Dec 2020 20:08:33 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 37/38] ccs-pll: Print pixel rates Date: Wed, 2 Dec 2020 20:06:40 +0200 Message-Id: <20201202180641.17401-38-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Print pixel rates on CSI-2 bus as well as in pixel array as the variation allowed in PLL capabilities makes this non-trivial to figure out otherwise. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs-pll.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c index 5a0162347777..eb7b6f01f623 100644 --- a/drivers/media/i2c/ccs-pll.c +++ b/drivers/media/i2c/ccs-pll.c @@ -119,6 +119,11 @@ static void print_pll(struct device *dev, struct ccs_pll *pll) } } + dev_dbg(dev, "pixel rate in pixel array:\t%u\n", + pll->pixel_rate_pixel_array); + dev_dbg(dev, "pixel rate on CSI-2 bus:\t%u\n", + pll->pixel_rate_csi); + dev_dbg(dev, "flags%s%s%s%s%s%s%s%s%s\n", pll->flags & PLL_FL(LANE_SPEED_MODEL) ? " lane-speed" : "", pll->flags & PLL_FL(LINK_DECOUPLED) ? " link-decoupled" : "", From patchwork Wed Dec 2 18:06:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 11946645 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B86BEC83014 for ; Wed, 2 Dec 2020 18:15:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7F71F206D5 for ; Wed, 2 Dec 2020 18:15:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389391AbgLBSP1 (ORCPT ); Wed, 2 Dec 2020 13:15:27 -0500 Received: from retiisi.eu ([95.216.213.190]:33490 "EHLO hillosipuli.retiisi.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2389385AbgLBSP1 (ORCPT ); Wed, 2 Dec 2020 13:15:27 -0500 Received: from lanttu.localdomain (lanttu-e.localdomain [192.168.1.64]) by hillosipuli.retiisi.eu (Postfix) with ESMTP id C8819634CD9; Wed, 2 Dec 2020 20:08:33 +0200 (EET) From: Sakari Ailus To: linux-media@vger.kernel.org Cc: mchehab@kernel.org Subject: [PATCH 38/38] ccs: Add support for obtaining C-PHY configuration from firmware Date: Wed, 2 Dec 2020 20:06:41 +0200 Message-Id: <20201202180641.17401-39-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201202180641.17401-1-sakari.ailus@linux.intel.com> References: <20201202180641.17401-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Try parsing the firmware also as C-PHY. Do this only after D-PHY as older firmware may not explicitly specify bus-type in which case D-PHY is the default. Signed-off-by: Sakari Ailus --- drivers/media/i2c/ccs/ccs-core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index c41c47b40e73..cd787155b698 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -2926,6 +2926,10 @@ static int ccs_get_hwconfig(struct ccs_sensor *sensor, struct device *dev) hwcfg->csi_signalling_mode = CCS_CSI_SIGNALING_MODE_CSI_2_DPHY; hwcfg->lanes = bus_cfg.bus.mipi_csi2.num_data_lanes; break; + case V4L2_MBUS_CSI2_CPHY: + hwcfg->csi_signalling_mode = CCS_CSI_SIGNALING_MODE_CSI_2_CPHY; + hwcfg->lanes = bus_cfg.bus.mipi_csi2.num_data_lanes; + break; case V4L2_MBUS_CSI1: case V4L2_MBUS_CCP2: hwcfg->csi_signalling_mode = (bus_cfg.bus.mipi_csi1.strobe) ?