All of lore.kernel.org
 help / color / mirror / Atom feed
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
To: Antti Palosaari <crope@iki.fi>
Cc: Ramesh Shanmugasundaram <ramesh.shanmugasundaram@bp.renesas.com>,
	robh+dt@kernel.org, mark.rutland@arm.com, mchehab@kernel.org,
	hverkuil@xs4all.nl, sakari.ailus@linux.intel.com,
	chris.paterson2@renesas.com, geert+renesas@glider.be,
	linux-media@vger.kernel.org, devicetree@vger.kernel.org,
	linux-renesas-soc@vger.kernel.org
Subject: Re: [PATCH 2/5] media: i2c: max2175: Add MAX2175 support
Date: Fri, 11 Nov 2016 13:50:03 +0200	[thread overview]
Message-ID: <46217523.VXi0bvqLS4@avalon> (raw)
In-Reply-To: <d9e9aac2-001c-491b-db34-a9eed6240722@iki.fi>

Hi Antti,

On Friday 11 Nov 2016 09:16:04 Antti Palosaari wrote:
> Hello
> 
> On 11/09/2016 05:44 PM, Ramesh Shanmugasundaram wrote:
> > +static int max2175_set_lo_freq(struct max2175 *ctx, u64 lo_freq)
> > +{
> > +	u64 scaled_lo_freq, scaled_npf, scaled_integer, scaled_fraction;
> > +	u32 frac_desired, int_desired, lo_mult = 1;
> > +	const u32 scale_factor = 1000000U;
> > +	u8 loband_bits = 0, vcodiv_bits = 0;
> > +	enum max2175_band band;
> > +	int ret;
> > +
> > +	/* Scale to larger number for precision */
> > +	scaled_lo_freq = lo_freq * scale_factor * 100;
> > +	band = max2175_read_bits(ctx, 5, 1, 0);
> > +
> > +	mxm_dbg(ctx, "set_lo_freq: scaled lo_freq %llu lo_freq %llu band 
%d\n",
> > +		scaled_lo_freq, lo_freq, band);
> > +
> > +	switch (band) {
> > +	case MAX2175_BAND_AM:
> > +		if (max2175_read_bit(ctx, 5, 7) == 0)
> > +			lo_mult = 16;
> 
> else is lo_mult = 1. No idea if it is correct, but sounds very small
> output divider for low freq like am band. And on the other-hand local
> oscillator output divider, which I expect this to be, is usually 2 or more.
> 
> > +		break;
> > +	case MAX2175_BAND_FM:
> > +		if (lo_freq <= 74700000) {
> > +			lo_mult = 16;
> 
> No meaning as you set it later 8.
> 
> > +		} else if (lo_freq > 74700000 && lo_freq <= 110000000) {
> > +			loband_bits = 1;
> > +		} else {
> > +			loband_bits = 1;
> > +			vcodiv_bits = 3;
> > +		}
> > +		lo_mult = 8;
> > +		break;
> > +	case MAX2175_BAND_VHF:
> > +		if (lo_freq <= 210000000) {
> > +			loband_bits = 2;
> > +			vcodiv_bits = 2;
> > +		} else {
> > +			loband_bits = 2;
> > +			vcodiv_bits = 1;
> > +		}
> > +		lo_mult = 4;
> > +		break;
> > +	default:
> > +		loband_bits = 3;
> > +		vcodiv_bits = 2;
> > +		lo_mult = 2;
> > +		break;
> > +	}
> > +
> > +	if (band == MAX2175_BAND_L)
> > +		scaled_npf = div_u64(div_u64(scaled_lo_freq, ctx->xtal_freq),
> > +				     lo_mult);
> > +	else
> > +		scaled_npf = div_u64(scaled_lo_freq, ctx->xtal_freq) * 
lo_mult;
> > +
> > +	scaled_npf = div_u64(scaled_npf, 100);
> > +	scaled_integer = div_u64(scaled_npf, scale_factor) * scale_factor;
> > +	int_desired = div_u64(scaled_npf, scale_factor);
> > +	scaled_fraction = scaled_npf - scaled_integer;
> > +	frac_desired = div_u64(scaled_fraction << 20, scale_factor);
> > +
> > +	/* Check CSM is not busy */
> > +	ret = max2175_poll_csm_ready(ctx);
> > +	if (ret)
> > +		return ret;
> > +
> > +	mxm_dbg(ctx, "loband %u vcodiv %u lo_mult %u scaled_npf %llu\n",
> > +		loband_bits, vcodiv_bits, lo_mult, scaled_npf);
> > +	mxm_dbg(ctx, "scaled int %llu frac %llu desired int %u frac %u\n",
> > +		scaled_integer, scaled_fraction, int_desired, frac_desired);
> > +
> > +	/* Write the calculated values to the appropriate registers */
> > +	max2175_write(ctx, 1, int_desired);
> > +	max2175_write_bits(ctx, 2, 3, 0, (frac_desired >> 16) & 0xf);
> > +	max2175_write(ctx, 3, frac_desired >> 8);
> > +	max2175_write(ctx, 4, frac_desired);
> > +	max2175_write_bits(ctx, 5, 3, 2, loband_bits);
> > +	max2175_write_bits(ctx, 6, 7, 6, vcodiv_bits);
> > +	return ret;
> > +}
> 
> That synthesizer config is hard to understand. It seems to be
> fractional-N, with configurable N, K and output divider - like a school
> book example.
> 
>                +----------------------------+
>                v                            |
>       Fref   +----+     +-------+         +------+
>      ------> | PD | --> |  VCO  | ------> | /N.F |
>              +----+     +-------+         +------+
>                           |
>                           |
>                           v
>                         +-------+  Fout
>                         | /Rout | ------>
>                         +-------+
>
> I made following look-up table in order to understand it:
> 
> band      lo freq band vcodiv div_out
>    AM  <  50000000    0      0      16 // reg 5 bit 7 ?
>    FM  <  74700000    0      0      16
>    FM  < 110000000    1      0       8
>    FM  < 160000000    1      3       8
>   VHF  < 210000000    2      2       4
>   VHF  < 600000000    2      1       4
>     L  <2000000000    3      2       2
> 
> "vcodiv" looks unrelated to synth calculation, dunno what it is.
> 
> One which makes calculation very complex looking is that it is based of
> floating point calculus. On integer mathematics you should replace
> fractional part with fractional modulus (usually letter "K" is used for
> fractional modulus on PLL calc).
> 
> So that ends up something like:
> 1) select suitable lo output divider from desired output frequency
> 2) calculate vco frequency
> 3) convert vco frequency to N and K
> * N = Fvco/Fref
> * K = Fvco%Fref
> 4) convert K to control word (looks like << 20)
> 5) program values
> 
> Result should be calculus without scaling.

Thanks for reviewing this part.

I'd like to add that we already have two PLL helpers in the media subsystem, 
in drivers/media/i2c/aptina-pll.c and drivers/media/i2c/smiapp-pll.c. As the 
PLL used here seems to be a classic one, it would make sense to also extract 
the code in a helper function that could be shared between drivers.

-- 
Regards,

Laurent Pinchart

WARNING: multiple messages have this Message-ID (diff)
From: Laurent Pinchart <laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw@public.gmane.org>
To: Antti Palosaari <crope-X3B1VOXEql0@public.gmane.org>
Cc: Ramesh Shanmugasundaram
	<ramesh.shanmugasundaram-kTT6dE0pTRh9uiUsa/gSgQ@public.gmane.org>,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
	mark.rutland-5wv7dgnIgG8@public.gmane.org,
	mchehab-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
	hverkuil-qWit8jRvyhVmR6Xm/wNWPw@public.gmane.org,
	sakari.ailus-VuQAYsv1563Yd54FQh9/CA@public.gmane.org,
	chris.paterson2-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org,
	geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org,
	linux-media-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: [PATCH 2/5] media: i2c: max2175: Add MAX2175 support
Date: Fri, 11 Nov 2016 13:50:03 +0200	[thread overview]
Message-ID: <46217523.VXi0bvqLS4@avalon> (raw)
In-Reply-To: <d9e9aac2-001c-491b-db34-a9eed6240722-X3B1VOXEql0@public.gmane.org>

Hi Antti,

On Friday 11 Nov 2016 09:16:04 Antti Palosaari wrote:
> Hello
> 
> On 11/09/2016 05:44 PM, Ramesh Shanmugasundaram wrote:
> > +static int max2175_set_lo_freq(struct max2175 *ctx, u64 lo_freq)
> > +{
> > +	u64 scaled_lo_freq, scaled_npf, scaled_integer, scaled_fraction;
> > +	u32 frac_desired, int_desired, lo_mult = 1;
> > +	const u32 scale_factor = 1000000U;
> > +	u8 loband_bits = 0, vcodiv_bits = 0;
> > +	enum max2175_band band;
> > +	int ret;
> > +
> > +	/* Scale to larger number for precision */
> > +	scaled_lo_freq = lo_freq * scale_factor * 100;
> > +	band = max2175_read_bits(ctx, 5, 1, 0);
> > +
> > +	mxm_dbg(ctx, "set_lo_freq: scaled lo_freq %llu lo_freq %llu band 
%d\n",
> > +		scaled_lo_freq, lo_freq, band);
> > +
> > +	switch (band) {
> > +	case MAX2175_BAND_AM:
> > +		if (max2175_read_bit(ctx, 5, 7) == 0)
> > +			lo_mult = 16;
> 
> else is lo_mult = 1. No idea if it is correct, but sounds very small
> output divider for low freq like am band. And on the other-hand local
> oscillator output divider, which I expect this to be, is usually 2 or more.
> 
> > +		break;
> > +	case MAX2175_BAND_FM:
> > +		if (lo_freq <= 74700000) {
> > +			lo_mult = 16;
> 
> No meaning as you set it later 8.
> 
> > +		} else if (lo_freq > 74700000 && lo_freq <= 110000000) {
> > +			loband_bits = 1;
> > +		} else {
> > +			loband_bits = 1;
> > +			vcodiv_bits = 3;
> > +		}
> > +		lo_mult = 8;
> > +		break;
> > +	case MAX2175_BAND_VHF:
> > +		if (lo_freq <= 210000000) {
> > +			loband_bits = 2;
> > +			vcodiv_bits = 2;
> > +		} else {
> > +			loband_bits = 2;
> > +			vcodiv_bits = 1;
> > +		}
> > +		lo_mult = 4;
> > +		break;
> > +	default:
> > +		loband_bits = 3;
> > +		vcodiv_bits = 2;
> > +		lo_mult = 2;
> > +		break;
> > +	}
> > +
> > +	if (band == MAX2175_BAND_L)
> > +		scaled_npf = div_u64(div_u64(scaled_lo_freq, ctx->xtal_freq),
> > +				     lo_mult);
> > +	else
> > +		scaled_npf = div_u64(scaled_lo_freq, ctx->xtal_freq) * 
lo_mult;
> > +
> > +	scaled_npf = div_u64(scaled_npf, 100);
> > +	scaled_integer = div_u64(scaled_npf, scale_factor) * scale_factor;
> > +	int_desired = div_u64(scaled_npf, scale_factor);
> > +	scaled_fraction = scaled_npf - scaled_integer;
> > +	frac_desired = div_u64(scaled_fraction << 20, scale_factor);
> > +
> > +	/* Check CSM is not busy */
> > +	ret = max2175_poll_csm_ready(ctx);
> > +	if (ret)
> > +		return ret;
> > +
> > +	mxm_dbg(ctx, "loband %u vcodiv %u lo_mult %u scaled_npf %llu\n",
> > +		loband_bits, vcodiv_bits, lo_mult, scaled_npf);
> > +	mxm_dbg(ctx, "scaled int %llu frac %llu desired int %u frac %u\n",
> > +		scaled_integer, scaled_fraction, int_desired, frac_desired);
> > +
> > +	/* Write the calculated values to the appropriate registers */
> > +	max2175_write(ctx, 1, int_desired);
> > +	max2175_write_bits(ctx, 2, 3, 0, (frac_desired >> 16) & 0xf);
> > +	max2175_write(ctx, 3, frac_desired >> 8);
> > +	max2175_write(ctx, 4, frac_desired);
> > +	max2175_write_bits(ctx, 5, 3, 2, loband_bits);
> > +	max2175_write_bits(ctx, 6, 7, 6, vcodiv_bits);
> > +	return ret;
> > +}
> 
> That synthesizer config is hard to understand. It seems to be
> fractional-N, with configurable N, K and output divider - like a school
> book example.
> 
>                +----------------------------+
>                v                            |
>       Fref   +----+     +-------+         +------+
>      ------> | PD | --> |  VCO  | ------> | /N.F |
>              +----+     +-------+         +------+
>                           |
>                           |
>                           v
>                         +-------+  Fout
>                         | /Rout | ------>
>                         +-------+
>
> I made following look-up table in order to understand it:
> 
> band      lo freq band vcodiv div_out
>    AM  <  50000000    0      0      16 // reg 5 bit 7 ?
>    FM  <  74700000    0      0      16
>    FM  < 110000000    1      0       8
>    FM  < 160000000    1      3       8
>   VHF  < 210000000    2      2       4
>   VHF  < 600000000    2      1       4
>     L  <2000000000    3      2       2
> 
> "vcodiv" looks unrelated to synth calculation, dunno what it is.
> 
> One which makes calculation very complex looking is that it is based of
> floating point calculus. On integer mathematics you should replace
> fractional part with fractional modulus (usually letter "K" is used for
> fractional modulus on PLL calc).
> 
> So that ends up something like:
> 1) select suitable lo output divider from desired output frequency
> 2) calculate vco frequency
> 3) convert vco frequency to N and K
> * N = Fvco/Fref
> * K = Fvco%Fref
> 4) convert K to control word (looks like << 20)
> 5) program values
> 
> Result should be calculus without scaling.

Thanks for reviewing this part.

I'd like to add that we already have two PLL helpers in the media subsystem, 
in drivers/media/i2c/aptina-pll.c and drivers/media/i2c/smiapp-pll.c. As the 
PLL used here seems to be a classic one, it would make sense to also extract 
the code in a helper function that could be shared between drivers.

-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

  reply	other threads:[~2016-11-11 11:50 UTC|newest]

Thread overview: 60+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-09 15:44 [PATCH 0/5] Add V4L2 SDR (DRIF & MAX2175) driver Ramesh Shanmugasundaram
2016-11-09 15:44 ` Ramesh Shanmugasundaram
2016-11-09 15:44 ` [PATCH 1/5] media: v4l2-ctrls: Reserve controls for MAX217X Ramesh Shanmugasundaram
2016-11-09 15:44 ` [PATCH 2/5] media: i2c: max2175: Add MAX2175 support Ramesh Shanmugasundaram
2016-11-09 15:44   ` Ramesh Shanmugasundaram
2016-11-11  7:16   ` Antti Palosaari
2016-11-11 11:50     ` Laurent Pinchart [this message]
2016-11-11 11:50       ` Laurent Pinchart
2016-11-11 13:21   ` Hans Verkuil
2016-11-11 13:48     ` Laurent Pinchart
2016-11-11 13:58       ` Hans Verkuil
2016-11-14 15:54     ` Ramesh Shanmugasundaram
2016-11-14 19:41   ` Rob Herring
2016-11-14 19:41     ` Rob Herring
2016-11-14 19:41     ` Rob Herring
2016-11-17 12:41     ` Ramesh Shanmugasundaram
2016-11-17 12:41       ` Ramesh Shanmugasundaram
2016-11-09 15:44 ` [PATCH 3/5] media: Add new SDR formats SC16, SC18 & SC20 Ramesh Shanmugasundaram
2016-11-11 13:24   ` Hans Verkuil
2016-11-11 13:48     ` Laurent Pinchart
2016-11-11 13:49     ` Laurent Pinchart
2016-11-14 16:20     ` Ramesh Shanmugasundaram
2016-11-14 16:52       ` Hans Verkuil
2016-11-09 15:44 ` [PATCH 4/5] doc_rst: media: New " Ramesh Shanmugasundaram
2016-11-09 15:44   ` Ramesh Shanmugasundaram
2016-11-10  8:18   ` Laurent Pinchart
2016-11-09 15:44 ` [PATCH 5/5] media: platform: rcar_drif: Add DRIF support Ramesh Shanmugasundaram
2016-11-10  9:22   ` Laurent Pinchart
2016-11-14 19:52     ` Rob Herring
2016-11-14 19:52       ` Rob Herring
2016-11-14 20:04       ` Geert Uytterhoeven
2016-11-14 20:04         ` Geert Uytterhoeven
2016-11-15 15:09         ` Ramesh Shanmugasundaram
2016-11-15 15:09           ` Ramesh Shanmugasundaram
2016-11-11 13:38   ` Hans Verkuil
2016-11-14 16:11     ` Ramesh Shanmugasundaram
2016-11-14 16:11       ` Ramesh Shanmugasundaram
2016-12-21  8:10 ` [PATCH v2 0/7] Add V4L2 SDR (DRIF & MAX2175) driver Ramesh Shanmugasundaram
2016-12-21  8:10   ` [PATCH v2 1/7] media: v4l2-ctrls: Reserve controls for MAX217X Ramesh Shanmugasundaram
2016-12-21  8:10   ` [PATCH v2 2/7] dt-bindings: media: Add MAX2175 binding description Ramesh Shanmugasundaram
2016-12-21  8:10   ` [PATCH v2 3/7] media: i2c: max2175: Add MAX2175 support Ramesh Shanmugasundaram
2016-12-21  8:10   ` [PATCH v2 4/7] media: Add new SDR formats PC16, PC18 & PC20 Ramesh Shanmugasundaram
2016-12-21  8:10   ` [PATCH v2 5/7] doc_rst: media: New " Ramesh Shanmugasundaram
2016-12-21  8:10     ` Ramesh Shanmugasundaram
2016-12-21  8:10   ` [PATCH v2 6/7] dt-bindings: media: Add Renesas R-Car DRIF binding Ramesh Shanmugasundaram
2016-12-22 17:05     ` Laurent Pinchart
2016-12-22 17:05       ` Laurent Pinchart
2016-12-22 19:05       ` Geert Uytterhoeven
2017-01-03 15:20         ` Ramesh Shanmugasundaram
2017-01-09 13:36           ` Hans Verkuil
2017-01-09 14:42             ` Ramesh Shanmugasundaram
2017-01-09 23:09             ` Laurent Pinchart
2017-01-09 23:09               ` Laurent Pinchart
2017-01-10  9:31               ` Ramesh Shanmugasundaram
2017-01-10  9:31                 ` Ramesh Shanmugasundaram
2017-01-19 17:46                 ` Chris Paterson
2017-01-27 11:20                 ` Hans Verkuil
2017-01-27 13:51                   ` Ramesh Shanmugasundaram
2017-01-27 13:51                     ` Ramesh Shanmugasundaram
2016-12-21  8:10   ` [PATCH v2 7/7] media: platform: rcar_drif: Add DRIF support Ramesh Shanmugasundaram

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=46217523.VXi0bvqLS4@avalon \
    --to=laurent.pinchart@ideasonboard.com \
    --cc=chris.paterson2@renesas.com \
    --cc=crope@iki.fi \
    --cc=devicetree@vger.kernel.org \
    --cc=geert+renesas@glider.be \
    --cc=hverkuil@xs4all.nl \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-renesas-soc@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mchehab@kernel.org \
    --cc=ramesh.shanmugasundaram@bp.renesas.com \
    --cc=robh+dt@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.