linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ramesh Shanmugasundaram <ramesh.shanmugasundaram@bp.renesas.com>
To: Hans Verkuil <hverkuil@xs4all.nl>,
	"robh+dt@kernel.org" <robh+dt@kernel.org>,
	"mark.rutland@arm.com" <mark.rutland@arm.com>,
	"mchehab@kernel.org" <mchehab@kernel.org>,
	"sakari.ailus@linux.intel.com" <sakari.ailus@linux.intel.com>,
	"crope@iki.fi" <crope@iki.fi>
Cc: Chris Paterson <Chris.Paterson2@renesas.com>,
	"laurent.pinchart@ideasonboard.com"
	<laurent.pinchart@ideasonboard.com>,
	"geert+renesas@glider.be" <geert+renesas@glider.be>,
	"linux-media@vger.kernel.org" <linux-media@vger.kernel.org>,
	"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
	"linux-renesas-soc@vger.kernel.org"
	<linux-renesas-soc@vger.kernel.org>
Subject: RE: [PATCH 2/5] media: i2c: max2175: Add MAX2175 support
Date: Mon, 14 Nov 2016 15:54:02 +0000	[thread overview]
Message-ID: <SG2PR06MB1038438380A78296C185D8E4C3BC0@SG2PR06MB1038.apcprd06.prod.outlook.com> (raw)
In-Reply-To: <46394837-c3f0-8487-750b-95dae7bcf859@xs4all.nl>

Hi Hans,

Thank you for the review comments.

> On 11/09/2016 04:44 PM, Ramesh Shanmugasundaram wrote:
> > This patch adds driver support for MAX2175 chip. This is Maxim
> > Integrated's RF to Bits tuner front end chip designed for
> > software-defined radio solutions. This driver exposes the tuner as a
> > sub-device instance with standard and custom controls to configure the
> device.
> >
> > Signed-off-by: Ramesh Shanmugasundaram
> > <ramesh.shanmugasundaram@bp.renesas.com>
> > ---
> >  .../devicetree/bindings/media/i2c/max2175.txt      |   61 +
> >  drivers/media/i2c/Kconfig                          |    4 +
> >  drivers/media/i2c/Makefile                         |    2 +
> >  drivers/media/i2c/max2175/Kconfig                  |    8 +
> >  drivers/media/i2c/max2175/Makefile                 |    4 +
> >  drivers/media/i2c/max2175/max2175.c                | 1558
> ++++++++++++++++++++
> >  drivers/media/i2c/max2175/max2175.h                |  108 ++
> >  7 files changed, 1745 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/media/i2c/max2175.txt
> >  create mode 100644 drivers/media/i2c/max2175/Kconfig  create mode
> > 100644 drivers/media/i2c/max2175/Makefile
> >  create mode 100644 drivers/media/i2c/max2175/max2175.c
> >  create mode 100644 drivers/media/i2c/max2175/max2175.h
> >
> 
> <snip>
> 
> > diff --git a/drivers/media/i2c/max2175/max2175.c
> > b/drivers/media/i2c/max2175/max2175.c
> > new file mode 100644
> > index 0000000..ec45b52
> > --- /dev/null
> > +++ b/drivers/media/i2c/max2175/max2175.c
> > @@ -0,0 +1,1558 @@
> 
> <snip>
> 
> > +/* Read/Write bit(s) on top of regmap */ static int
> > +max2175_read(struct max2175 *ctx, u8 idx, u8 *val) {
> > +	u32 regval;
> > +	int ret = regmap_read(ctx->regmap, idx, &regval);
> > +
> > +	if (ret)
> > +		v4l2_err(ctx->client, "read ret(%d): idx 0x%02x\n", ret, idx);
> > +
> > +	*val = regval;
> 
> Does regmap_read initialize regval even if it returns an error? If not,
> then I would initialize regval to 0 to prevent *val being uninitialized.

Agreed.

> 
> > +	return ret;
> > +}
> > +
> > +static int max2175_write(struct max2175 *ctx, u8 idx, u8 val) {
> > +	int ret = regmap_write(ctx->regmap, idx, val);
> > +
> > +	if (ret)
> > +		v4l2_err(ctx->client, "write ret(%d): idx 0x%02x val
> 0x%02x\n",
> > +			 ret, idx, val);
> > +	return ret;
> > +}
> > +
> > +static u8 max2175_read_bits(struct max2175 *ctx, u8 idx, u8 msb, u8
> > +lsb) {
> > +	u8 val;
> > +
> > +	if (max2175_read(ctx, idx, &val))
> > +		return 0;
> > +
> > +	return max2175_get_bitval(val, msb, lsb); }
> > +
> > +static bool max2175_read_bit(struct max2175 *ctx, u8 idx, u8 bit) {
> > +	return !!max2175_read_bits(ctx, idx, bit, bit); }
> > +
> > +static int max2175_write_bits(struct max2175 *ctx, u8 idx,
> > +			     u8 msb, u8 lsb, u8 newval)
> > +{
> > +	int ret = regmap_update_bits(ctx->regmap, idx, GENMASK(msb, lsb),
> > +				     newval << lsb);
> > +
> > +	if (ret)
> > +		v4l2_err(ctx->client, "wbits ret(%d): idx 0x%02x\n", ret,
> idx);
> > +
> > +	return ret;
> > +}
> > +
> > +static int max2175_write_bit(struct max2175 *ctx, u8 idx, u8 bit, u8
> > +newval) {
> > +	return max2175_write_bits(ctx, idx, bit, bit, newval); }
> > +
> > +/* Checks expected pattern every msec until timeout */ static int
> > +max2175_poll_timeout(struct max2175 *ctx, u8 idx, u8 msb, u8 lsb,
> > +				u8 exp_bitval, u32 timeout_ms)
> > +{
> > +	unsigned int val;
> > +
> > +	return regmap_read_poll_timeout(ctx->regmap, idx, val,
> > +			(max2175_get_bitval(val, msb, lsb) == exp_bitval),
> > +			1000, timeout_ms * 1000);
> > +}
> > +
> > +static int max2175_poll_csm_ready(struct max2175 *ctx) {
> > +	int ret;
> > +
> > +	ret = max2175_poll_timeout(ctx, 69, 1, 1, 0, 50);
> > +	if (ret)
> > +		v4l2_err(ctx->client, "csm not ready\n");
> > +
> > +	return ret;
> > +}
> > +
> > +#define MAX2175_IS_BAND_AM(ctx)		\
> > +	(max2175_read_bits(ctx, 5, 1, 0) == MAX2175_BAND_AM)
> > +
> > +#define MAX2175_IS_BAND_VHF(ctx)	\
> > +	(max2175_read_bits(ctx, 5, 1, 0) == MAX2175_BAND_VHF)
> > +
> > +#define MAX2175_IS_FM_MODE(ctx)		\
> > +	(max2175_read_bits(ctx, 12, 5, 4) == 0)
> > +
> > +#define MAX2175_IS_FMHD_MODE(ctx)	\
> > +	(max2175_read_bits(ctx, 12, 5, 4) == 1)
> > +
> > +#define MAX2175_IS_DAB_MODE(ctx)	\
> > +	(max2175_read_bits(ctx, 12, 5, 4) == 2)
> > +
> > +static int max2175_band_from_freq(u32 freq) {
> > +	if (freq >= 144000 && freq <= 26100000)
> > +		return MAX2175_BAND_AM;
> > +	else if (freq >= 65000000 && freq <= 108000000)
> > +		return MAX2175_BAND_FM;
> > +	else
> 
> No need for these 'else' keywords.

Agreed.

> 
> > +		return MAX2175_BAND_VHF;
> > +}
> > +
> > +static int max2175_update_i2s_mode(struct max2175 *ctx, u32 rx_mode,
> > +				   u32 i2s_mode)
> > +{
> > +	max2175_write_bits(ctx, 29, 2, 0, i2s_mode);
> > +
> > +	/* Based on I2S mode value I2S_WORD_CNT values change */
> > +	switch (i2s_mode) {
> > +	case MAX2175_I2S_MODE3:
> > +		max2175_write_bits(ctx, 30, 6, 0, 1);
> > +		break;
> > +	case MAX2175_I2S_MODE2:
> > +	case MAX2175_I2S_MODE4:
> > +		max2175_write_bits(ctx, 30, 6, 0, 0);
> > +		break;
> > +	case MAX2175_I2S_MODE0:
> > +		max2175_write_bits(ctx, 30, 6, 0,
> > +			ctx->rx_modes[rx_mode].i2s_word_size);
> > +		break;
> > +	}
> > +	mxm_dbg(ctx, "update_i2s_mode %u, rx_mode %u\n", i2s_mode, rx_mode);
> > +	return 0;
> > +}

[snip]

> > +
> > +static int max2175_enum_freq_bands(struct v4l2_subdev *sd,
> > +			    struct v4l2_frequency_band *band) {
> > +	struct max2175 *ctx = max2175_from_sd(sd);
> > +
> > +	if (band->tuner == 0 && band->index == 0)
> > +		*band = *ctx->bands_rf;
> > +	else
> > +		return -EINVAL;
> 
> This is a bit ugly. I would invert the condition and return -EINVAL.
> Then assign *band and return 0.

Agreed.

> 
> > +
> > +	return 0;
> > +}
> > +
> > +static int max2175_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner
> > +*vt) {
> > +	struct max2175 *ctx = max2175_from_sd(sd);
> > +
> > +	if (vt->index > 0)
> > +		return -EINVAL;
> > +
> > +	strlcpy(vt->name, "RF", sizeof(vt->name));
> > +	vt->type = V4L2_TUNER_RF;
> > +	vt->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
> > +	vt->rangelow = ctx->bands_rf->rangelow;
> > +	vt->rangehigh = ctx->bands_rf->rangehigh;
> > +	return 0;
> > +}
> > +
> > +static int max2175_s_tuner(struct v4l2_subdev *sd, const struct
> > +v4l2_tuner *vt) {
> > +	/* Check tuner index is valid */
> > +	if (vt->index > 0)
> > +		return -EINVAL;
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct v4l2_subdev_tuner_ops max2175_tuner_ops = {
> > +	.s_frequency = max2175_s_frequency,
> > +	.g_frequency = max2175_g_frequency,
> > +	.enum_freq_bands = max2175_enum_freq_bands,
> > +	.g_tuner = max2175_g_tuner,
> > +	.s_tuner = max2175_s_tuner,
> > +};
> > +
> > +static const struct v4l2_subdev_ops max2175_ops = {
> > +	.tuner = &max2175_tuner_ops,
> > +};
> > +
> > +static const struct v4l2_ctrl_ops max2175_ctrl_ops = {
> > +	.s_ctrl = max2175_s_ctrl,
> > +	.g_volatile_ctrl = max2175_g_volatile_ctrl, };
> > +
> > +static const struct v4l2_ctrl_config max2175_i2s_en = {
> > +	.ops = &max2175_ctrl_ops,
> > +	.id = V4L2_CID_MAX2175_I2S_ENABLE,
> > +	.name = "I2S Enable",
> > +	.type = V4L2_CTRL_TYPE_BOOLEAN,
> > +	.min = 0,
> > +	.max = 1,
> > +	.step = 1,
> > +	.def = 1,
> > +};
> > +
> > +static const char * const max2175_ctrl_i2s_modes[] = {
> > +	[MAX2175_I2S_MODE0]	= "i2s mode 0",
> > +	[MAX2175_I2S_MODE1]	= "i2s mode 1 (skipped)",
> > +	[MAX2175_I2S_MODE2]	= "i2s mode 2",
> > +	[MAX2175_I2S_MODE3]	= "i2s mode 3",
> > +	[MAX2175_I2S_MODE4]	= "i2s mode 4",
> > +};
> > +
> > +static const struct v4l2_ctrl_config max2175_i2s_mode = {
> > +	.ops = &max2175_ctrl_ops,
> > +	.id = V4L2_CID_MAX2175_I2S_MODE,
> > +	.name = "I2S MODE value",
> > +	.type = V4L2_CTRL_TYPE_MENU,
> > +	.max = ARRAY_SIZE(max2175_ctrl_i2s_modes) - 1,
> > +	.def = 0,
> > +	.menu_skip_mask = 0x02,
> > +	.qmenu = max2175_ctrl_i2s_modes,
> > +};
> 
> Is this something that is changed dynamically? It looks more like a device
> tree thing (it's not clear what it does, so obviously I can't be sure).

Yes. It can be changed dynamically. 

> 
> > +
> > +static const struct v4l2_ctrl_config max2175_hsls = {
> > +	.ops = &max2175_ctrl_ops,
> > +	.id = V4L2_CID_MAX2175_HSLS,
> > +	.name = "HSLS above/below desired",
> > +	.type = V4L2_CTRL_TYPE_INTEGER,
> > +	.min = 0,
> > +	.max = 1,
> > +	.step = 1,
> > +	.def = 1,
> > +};
> > +
> > +static const char * const max2175_ctrl_eu_rx_modes[] = {
> > +	[MAX2175_EU_FM_1_2]	= "EU FM 1.2",
> > +	[MAX2175_DAB_1_2]	= "DAB 1.2",
> > +};
> > +
> > +static const char * const max2175_ctrl_na_rx_modes[] = {
> > +	[MAX2175_NA_FM_1_0]	= "NA FM 1.0",
> > +	[MAX2175_NA_FM_2_0]	= "NA FM 2.0",
> > +};
> > +
> > +static const struct v4l2_ctrl_config max2175_eu_rx_mode = {
> > +	.ops = &max2175_ctrl_ops,
> > +	.id = V4L2_CID_MAX2175_RX_MODE,
> > +	.name = "RX MODE",
> > +	.type = V4L2_CTRL_TYPE_MENU,
> > +	.max = ARRAY_SIZE(max2175_ctrl_eu_rx_modes) - 1,
> > +	.def = 0,
> > +	.qmenu = max2175_ctrl_eu_rx_modes,
> > +};
> > +
> > +static const struct v4l2_ctrl_config max2175_na_rx_mode = {
> > +	.ops = &max2175_ctrl_ops,
> > +	.id = V4L2_CID_MAX2175_RX_MODE,
> > +	.name = "RX MODE",
> > +	.type = V4L2_CTRL_TYPE_MENU,
> > +	.max = ARRAY_SIZE(max2175_ctrl_na_rx_modes) - 1,
> > +	.def = 0,
> > +	.qmenu = max2175_ctrl_na_rx_modes,
> > +};
> 
> Please document all these controls better. This is part of the public API,
> so you need to give more information what this means exactly.

Thanks. Now, I have added a one-liner and a bit descriptive explanation at Documentation/media/v4l-drivers dir as you & Laurent concluded.

Thanks,
Ramesh

  parent reply	other threads:[~2016-11-14 15:54 UTC|newest]

Thread overview: 44+ 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 ` [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-11  7:16   ` Antti Palosaari
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 [this message]
2016-11-14 19:41   ` Rob Herring
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-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 20:04       ` Geert Uytterhoeven
2016-11-15 15:09         ` Ramesh Shanmugasundaram
2016-11-11 13:38   ` Hans Verkuil
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   ` [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 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-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
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=SG2PR06MB1038438380A78296C185D8E4C3BC0@SG2PR06MB1038.apcprd06.prod.outlook.com \
    --to=ramesh.shanmugasundaram@bp.renesas.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=laurent.pinchart@ideasonboard.com \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-renesas-soc@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mchehab@kernel.org \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).