All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
To: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
	linux-media@vger.kernel.org
Cc: Sakari Ailus <sakari.ailus@linux.intel.com>,
	Benoit Parrot <bparrot@ti.com>
Subject: Re: [PATCH 2/2] media: i2c: Add OV1063x sensor driver
Date: Mon, 18 Jan 2021 16:04:47 +0200	[thread overview]
Message-ID: <515e6893-7f49-ee4a-1f22-96f5aa38d938@ideasonboard.com> (raw)
In-Reply-To: <20210104053945.12409-3-laurent.pinchart@ideasonboard.com>

Hi Laurent,

On 04/01/2021 07:39, Laurent Pinchart wrote:

> +static int ov1063x_pll_setup(unsigned int clk_rate,
> +			     unsigned int *htsmin, unsigned int vts,
> +			     unsigned int fps_numerator,
> +			     unsigned int fps_denominator,
> +			     struct ov1063x_pll_config *cfg)
> +{
> +	static const unsigned int pre_divs[] = { 2, 3, 4, 6, 8, 10, 12, 14 };
> +
> +	unsigned int best_pclk = UINT_MAX;
> +	unsigned int best_pre_div;
> +	unsigned int best_mult;
> +	unsigned int best_div;
> +	unsigned int best_hts;
> +	unsigned int max_pre_div;
> +	unsigned int pre_div;
> +	unsigned int hts;
> +
> +	/*
> +	 *  XVCLK --> pre-div -------> mult ----------> div --> output
> +	 * 6-27 MHz           3-27 MHz      200-500 MHz       Max 96 MHz
> +	 *
> +	 * Valid pre-divider values are 1, 1.5, 2, 3, 4, 5, 6 and 7. The
> +	 * pre_divs array stores the pre-dividers multiplied by two, indexed by
> +	 * register values.
> +	 *
> +	 * Valid multiplier values are [1, 63], stored as-is in registers.
> +	 *
> +	 * Valid divider values are 2 to 16 with a step of 2, stored in
> +	 * registers as (div / 2) - 1.
> +	 */
> +
> +	if (clk_rate < 6 * 1000 * 1000 || clk_rate > 27 * 1000 * 1000)
> +		return -EINVAL;
> +
> +	/*
> +	 * We try all valid combinations of settings for the 3 blocks to get
> +	 * the pixel clock, and from that calculate the actual hts/vts to use.
> +	 * The vts is extended so as to achieve the required frame rate.
> +	 */
> +
> +	max_pre_div = max(clk_rate / (3 * 1000 * 1000),
> +			  ARRAY_SIZE(pre_divs) - 1);
> +
> +	for (pre_div = 0; pre_div <= max_pre_div; pre_div++) {
> +		unsigned int clk1 = clk_rate * 2 / pre_divs[pre_div];
> +		unsigned int min_mult;
> +		unsigned int max_mult;
> +		unsigned int mult;

This PLL setup is a bit confusing to understand, because:

- "pre_div" is not the divider value, but an index to the pre_divs array
and a value to be written into the register, and pre_div is also stored
into the pll_cfg.

- "div" _is_ the divider value but it's not stored into the pll_cfg,
instead (div / 2) - 1 is stored there.

And calculating max_pre_div is probably not right above, I think it
should be min(), and additionally "clk_rate / (3 * 1000 * 1000)" is
calculating the divider value, not the index, but it's then used as a
max to the index loop... And even if it were the index, it should be -1,
as the loop check uses <=.

Suggestions:

- Redefine the PLL formula. Instead of having fractional pre_divider (I
wonder if it's actually fractional in the HW... Aren't dividers usually
integer dividers?), redefine the formula as pclk = xvclk * 2 / pre_div *
mul / div, and say that the possible pre_dividers are what's currently
in pre_divs array. Or pclk = xvclk / pre_div * 2 * mul / div, which
gives a different result with integer divisions. I don't know which one
is the correct one (or is it either of those... If the HW handles
fractionals, both are wrong).

- Clearly separate divider value and index/regvalue variables. The
iteration loop should use the plain divider values, and I think it would
be best to store the values as such to pll_config. And map the divider
values to register values only when writing to the register.

 Tomi

  parent reply	other threads:[~2021-01-18 14:06 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-04  5:39 [PATCH 0/2] media: Driver for OV1063x camera sensor Laurent Pinchart
2021-01-04  5:39 ` [PATCH 1/2] dt-bindings: media: Add bindings for OmniVision OV1063x sensors Laurent Pinchart
2021-01-05 17:49   ` Rob Herring
2021-01-12  9:31   ` Tomi Valkeinen
2021-01-04  5:39 ` [PATCH 2/2] media: i2c: Add OV1063x sensor driver Laurent Pinchart
2021-01-04 11:41   ` Sakari Ailus
2021-01-04 13:56     ` Laurent Pinchart
2021-12-06 22:23     ` Laurent Pinchart
2021-01-04 12:47   ` Sakari Ailus
2021-01-04 13:05     ` Laurent Pinchart
2021-01-04 13:55       ` Sakari Ailus
2021-01-12 13:32   ` Tomi Valkeinen
2021-01-14  5:32     ` Laurent Pinchart
2021-01-18 14:04   ` Tomi Valkeinen [this message]
2021-01-20  8:26     ` Laurent Pinchart
2021-01-20 11:52       ` Tomi Valkeinen
2021-02-08 14:18   ` Tomi Valkeinen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=515e6893-7f49-ee4a-1f22-96f5aa38d938@ideasonboard.com \
    --to=tomi.valkeinen@ideasonboard.com \
    --cc=bparrot@ti.com \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linux-media@vger.kernel.org \
    --cc=sakari.ailus@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.