All of lore.kernel.org
 help / color / mirror / Atom feed
From: Geert Uytterhoeven <geert-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org>
To: Ramesh Shanmugasundaram
	<ramesh.shanmugasundaram-kTT6dE0pTRh9uiUsa/gSgQ@public.gmane.org>
Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
	Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>,
	Mauro Carvalho Chehab
	<mchehab-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
	Hans Verkuil <hverkuil-qWit8jRvyhVmR6Xm/wNWPw@public.gmane.org>,
	Sakari Ailus
	<sakari.ailus-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>,
	Antti Palosaari <crope-X3B1VOXEql0@public.gmane.org>,
	Chris Paterson
	<chris.paterson2-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org>,
	Laurent Pinchart
	<laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw@public.gmane.org>,
	Linux Media Mailing List
	<linux-media-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
	"devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org"
	<devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
	Linux-Renesas
	<linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
Subject: Re: [RFC 1/5] media: i2c: max2175: Add MAX2175 support
Date: Sat, 15 Oct 2016 14:42:18 +0200	[thread overview]
Message-ID: <CAMuHMdUYQoJL4h8prEpontF4YH8Ha+SWDdeZHYEV3_uMZ-SBXw@mail.gmail.com> (raw)
In-Reply-To: <1476281429-27603-2-git-send-email-ramesh.shanmugasundaram-kTT6dE0pTRh9uiUsa/gSgQ@public.gmane.org>

Hi Ramesh,

On Wed, Oct 12, 2016 at 4:10 PM, Ramesh Shanmugasundaram
<ramesh.shanmugasundaram-kTT6dE0pTRh9uiUsa/gSgQ@public.gmane.org> 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 < for your patch!amesh.shanmugasundaram-kTT6dE0pTRh9uiUsa/gSgQ@public.gmane.org>

Thanks for your patch!

> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/i2c/max2175.txt
> @@ -0,0 +1,60 @@
> +Maxim Integrated MAX2175 RF to Bits tuner
> +-----------------------------------------
> +
> +The MAX2175 IC is an advanced analog/digital hybrid-radio receiver with
> +RF to Bits® front-end designed for software-defined radio solutions.
> +
> +Required properties:
> +--------------------
> +- compatible: "maxim,max2175" for MAX2175 RF-to-bits tuner.
> +- clocks: phandle to the fixed xtal clock.
> +- clock-names: name of the fixed xtal clock.
> +- port: video interface child port node of a tuner that defines the local
> +  and remote endpoints. The remote endpoint is assumed to be an SDR device
> +  that is capable of receiving the digital samples from the tuner.
> +
> +Optional properties:
> +--------------------
> +- maxim,slave     : empty property indicates this is a slave of another
> +                    master tuner. This is used to define two tuners in
> +                    diversity mode (1 master, 1 slave). By default each
> +                    tuner is an individual master.
> +- maxim,refout-load: load capacitance value (in pF) on reference output
> +                    drive level. The mapping of these load values to
> +                    respective bit values are given below.
> +                    0 - Reference output disabled
> +                    1 - 10pF load
> +                    2 - 20pF load
> +                    3 - 30pF load
> +                    4 - 40pF load
> +                    5 - 60pF load
> +                    6 - 70pF load

For properties involving units, usually the unit is made part of the
property name, e.g. maxim,refout-load-pF = 40.
This avoids confusion, and allows for extension later.

> +/* A tuner device instance under i2c bus */
> +max2175_0: tuner@60 {
> +       #clock-cells = <0>;
> +       compatible = "maxim,max2175";
> +       reg = <0x60>;
> +       clocks = <&maxim_xtal>;
> +       clock-names = "xtal";
> +       maxim,refout-load = <10>;

10 is not listed above. Perhaps you meant 10 pF?

> --- /dev/null
> +++ b/drivers/media/i2c/max2175/max2175.c
> @@ -0,0 +1,1624 @@

> +/* NOTE: Any addition/deletion in the below list should be reflected in
> + * max2175_modetag enum
> + */

You can drop the above comment if you make this explicit using C99
designated initializers, cfr. below.

> +static const struct max2175_rxmode eu_rx_modes[] = { /* Indexed by EU modetag */
> +       /* EU modes */
> +       { MAX2175_BAND_VHF, 182640000, 0, { 0, 0, 0, 0 } },

[MAX2175_DAB_1_2] = { MAX2175_BAND_VHF, 182640000, 0, { 0, 0, 0, 0 } },

> +};
> +
> +static const struct max2175_rxmode na_rx_modes[] = { /* Indexed by NA modetag */
> +       /* NA modes */
> +       { MAX2175_BAND_FM, 98255520, 1, { 0, 0, 0, 0 } },

[MAX2175_NA_FM_1_0] = { MAX2175_BAND_FM, 98255520, 1, { 0, 0, 0, 0 } },

> +struct max2175_ctx {
> +       struct v4l2_subdev sd;
> +       struct i2c_client *client;
> +       struct device *dev;
> +
> +       /* Cached configuration */
> +       u8 regs[256];
> +       enum max2175_modetag mode;      /* Receive mode tag */
> +       u32 freq;                       /* In Hz */
> +       struct max2175_rxmode *rx_modes;
> +
> +       /* Device settings */
> +       bool master;
> +       u32 decim_ratio;
> +       u64 xtal_freq;
> +
> +       /* ROM values */
> +       u8 rom_bbf_bw_am;
> +       u8 rom_bbf_bw_fm;
> +       u8 rom_bbf_bw_dab;
> +
> +       /* Local copy of old settings */
> +       u8 i2s_test;
> +
> +       u8 nbd_gain;
> +       u8 nbd_threshold;
> +       u8 wbd_gain;
> +       u8 wbd_threshold;
> +       u8 bbd_threshold;
> +       u8 bbdclip_threshold;
> +       u8 lt_wbd_threshold;
> +       u8 lt_wbd_gain;
> +
> +       /* Controls */
> +       struct v4l2_ctrl_handler ctrl_hdl;
> +       struct v4l2_ctrl *lna_gain;     /* LNA gain value */
> +       struct v4l2_ctrl *if_gain;      /* I/F gain value */
> +       struct v4l2_ctrl *pll_lock;     /* PLL lock */
> +       struct v4l2_ctrl *i2s_en;       /* I2S output enable */
> +       struct v4l2_ctrl *i2s_mode;     /* I2S mode value */
> +       struct v4l2_ctrl *am_hiz;       /* AM High impledance input */
> +       struct v4l2_ctrl *hsls;         /* High-side/Low-side polarity */
> +       struct v4l2_ctrl *rx_mode;      /* Receive mode */
> +
> +       /* Driver private variables */
> +       bool mode_resolved;             /* Flag to sanity check settings */
> +};

Sorting the struct members by decreasing size helps to avoid gaps due to
alignment restrictions, and may reduce memory consumption.

> +/* Flush local copy to device from idx to idx+len (inclusive) */
> +static void max2175_flush_regstore(struct max2175_ctx *ctx, u8 idx, u8 len)
> +{
> +       u8 i;

I'd just use unsigned int for loop counters.

> +
> +       for (i = idx; i <= len; i++)
> +               max2175_reg_write(ctx, i, ctx->regs[i]);
> +}

> +static int max2175_update_i2s_mode(struct max2175_ctx *ctx, u32 i2s_mode)
> +{
> +       /* Only change if it's new */
> +       if (max2175_read_bits(ctx, 29, 2, 0) == i2s_mode)

Many magic numbers, not only here (29, 2), but everywhere.
Can you please add #defines for these?

> +               return 0;
> +
> +       max2175_write_bits(ctx, 29, 2, 0, i2s_mode);
> +
> +       /* Based on I2S mode value I2S_WORD_CNT values change */
> +       if (i2s_mode == MAX2175_I2S_MODE3) {
> +               max2175_write_bits(ctx, 30, 6, 0, 1);
> +       } else if (i2s_mode == MAX2175_I2S_MODE2 ||
> +                  i2s_mode == MAX2175_I2S_MODE4) {
> +               max2175_write_bits(ctx, 30, 6, 0, 0);
> +       } else if (i2s_mode == MAX2175_I2S_MODE0) {
> +               max2175_write_bits(ctx, 30, 6, 0,
> +                                  ctx->rx_modes[ctx->mode].i2s_word_size);
> +       } else {
> +               v4l2_err(ctx->client,
> +                        "failed: i2s_mode %u unsupported\n", i2s_mode);
> +               return 1;
> +       }

switch (i2s_mode) { ... }

> +       mxm_dbg(ctx, "updated i2s_mode %u\n", i2s_mode);
> +       return 0;
> +}

> +static void max2175_set_filter_coeffs(struct max2175_ctx *ctx, u8 m_sel,
> +                                     u8 bank, const u16 *coeffs)
> +{
> +       u8 i, coeff_addr, upper_address;

I'd just use unsigned int for these.

> +
> +       mxm_dbg(ctx, "start: m_sel %d bank %d\n", m_sel, bank);
> +       max2175_write_bits(ctx, 114, 5, 4, m_sel);
> +
> +       if (m_sel == 2)
> +               upper_address = 12;
> +       else
> +               upper_address = 24;
> +
> +       max2175_set_bit(ctx, 117, 7, 1);
> +       for (i = 0; i < upper_address; i++) {
> +               coeff_addr = i + (bank * 24);
> +               max2175_set_bits(ctx, 115, 7, 0,
> +                                (u8)((coeffs[i] >> 8) & 0xff));
> +               max2175_set_bits(ctx, 116, 7, 0, (u8)(coeffs[i] & 0xff));

I don't think you need the casts to u8, or the masking with 0xff.

> +               max2175_set_bits(ctx, 117, 6, 0, coeff_addr);
> +               max2175_flush_regstore(ctx, 115, 3);
> +       }
> +       max2175_write_bit(ctx, 117, 7, 0);
> +}
> +
> +static void max2175_load_dab_1p2(struct max2175_ctx *ctx)
> +{
> +       u32 i;

unsigned int?

> +static int max2175_set_lo_freq(struct max2175_ctx *ctx, u64 lo_freq)
> +{
> +       int ret;
> +       u32 lo_mult;
> +       u64 scaled_lo_freq;
> +       const u64 scale_factor = 1000000ULL;
> +       u64 scaled_npf, scaled_integer, scaled_fraction;
> +       u32 frac_desired, int_desired;
> +       u8 loband_bits, vcodiv_bits;
> +
> +       scaled_lo_freq = lo_freq;
> +       /* Scale to larger number for precision */
> +       scaled_lo_freq = scaled_lo_freq * scale_factor * 100;
> +
> +       mxm_dbg(ctx, "scaled lo_freq %llu lo_freq %llu\n",
> +               scaled_lo_freq, lo_freq);
> +
> +       if (MAX2175_IS_BAND_AM(ctx)) {
> +               if (max2175_get_bit(ctx, 5, 7) == 0)
> +                       loband_bits = 0;
> +                       vcodiv_bits = 0;
> +                       lo_mult = 16;
> +       } else if (max2175_get_bits(ctx, 5, 1, 0) == MAX2175_BAND_FM) {
> +               if (lo_freq <= 74700000) {
> +                       loband_bits = 0;
> +                       vcodiv_bits = 0;
> +                       lo_mult = 16;
> +               } else if ((lo_freq > 74700000) && (lo_freq <= 110000000)) {
> +                       loband_bits = 1;
> +                       vcodiv_bits = 0;
> +               } else {
> +                       loband_bits = 1;
> +                       vcodiv_bits = 3;
> +               }
> +               lo_mult = 8;
> +       } else if (max2175_get_bits(ctx, 5, 1, 0) == MAX2175_BAND_VHF) {
> +               if (lo_freq <= 210000000) {
> +                       loband_bits = 2;
> +                       vcodiv_bits = 2;
> +               } else {
> +                       loband_bits = 2;
> +                       vcodiv_bits = 1;
> +               }
> +               lo_mult = 4;
> +       } else {
> +               loband_bits = 3;
> +               vcodiv_bits = 2;
> +               lo_mult = 2;
> +       }
> +
> +       if (max2175_get_bits(ctx, 5, 1, 0) == MAX2175_BAND_L)
> +               scaled_npf = (scaled_lo_freq / ctx->xtal_freq / lo_mult) / 100;
> +       else
> +               scaled_npf = (scaled_lo_freq / ctx->xtal_freq * lo_mult) / 100;

Please use one of the div64*() functions for divisions involving 64-bit
quantities (try to build for 32-bit and see). More of these below...

> +       scaled_integer = scaled_npf / scale_factor * scale_factor;
> +       int_desired = (u32)(scaled_npf / scale_factor);
> +       scaled_fraction = scaled_npf - scaled_integer;
> +       frac_desired = (u32)(scaled_fraction * 1048576 / scale_factor);

> +       /* Write the calculated values to the appropriate registers */
> +       max2175_set_bits(ctx, 5, 3, 2, loband_bits);
> +       max2175_set_bits(ctx, 6, 7, 6, vcodiv_bits);
> +       max2175_set_bits(ctx, 1, 7, 0, (u8)(int_desired & 0xff));
> +       max2175_set_bits(ctx, 2, 3, 0, (u8)((frac_desired >> 16) & 0x1f));
> +       max2175_set_bits(ctx, 3, 7, 0, (u8)((frac_desired >> 8) & 0xff));
> +       max2175_set_bits(ctx, 4, 7, 0, (u8)(frac_desired & 0xff));

No need for casts etc.

> +       /* Flush the above registers to device */
> +       max2175_flush_regstore(ctx, 1, 6);
> +       return ret;
> +}
> +
> +static int max2175_set_nco_freq(struct max2175_ctx *ctx, s64 nco_freq_desired)
> +{
> +       int ret;
> +       u64 clock_rate, abs_nco_freq;
> +       s64  nco_freq, nco_val_desired;
> +       u32 nco_reg;
> +       const u64 scale_factor = 1000000ULL;
> +
> +       mxm_dbg(ctx, "nco_freq: freq = %lld\n", nco_freq_desired);
> +       clock_rate = ctx->xtal_freq / ctx->decim_ratio;
> +       nco_freq = -nco_freq_desired;
> +
> +       if (nco_freq < 0)
> +               abs_nco_freq = -nco_freq;
> +       else
> +               abs_nco_freq = nco_freq;
> +
> +       /* Scale up the values for precision */
> +       if (abs_nco_freq < (clock_rate / 2)) {
> +               nco_val_desired = (2 * nco_freq * scale_factor) / clock_rate;
> +       } else {
> +               if (nco_freq < 0)
> +                       nco_val_desired = (-2 * (clock_rate - abs_nco_freq) *
> +                               scale_factor) / clock_rate;
> +               else
> +                       nco_val_desired = (2 * (clock_rate - abs_nco_freq) *
> +                               scale_factor) / clock_rate;
> +       }
> +
> +       /* Scale down to get the fraction */
> +       if (nco_freq < 0)
> +               nco_reg = 0x200000 + ((nco_val_desired * 1048576) /
> +                                     scale_factor);
> +       else
> +               nco_reg = (nco_val_desired * 1048576) / scale_factor;

More 64-bit divisions. In addition, the dividers are 64-bit too.
Can't they be 32-bit?

> +static int max2175_probe(struct i2c_client *client,
> +                       const struct i2c_device_id *id)
> +{
> +       struct max2175_ctx *ctx;
> +       struct device *dev = &client->dev;
> +       struct v4l2_subdev *sd;
> +       struct v4l2_ctrl_handler *hdl;
> +       struct clk *clk;
> +       bool master = true;
> +       u32 refout_load, refout_bits = 0;       /* REFOUT disabled */
> +       int ret;
> +
> +       /* Check if the adapter supports the needed features */
> +       if (!i2c_check_functionality(client->adapter,
> +                                    I2C_FUNC_SMBUS_BYTE_DATA)) {
> +               dev_err(&client->dev, "i2c check failed\n");
> +               return -EIO;
> +       }
> +
> +       if (of_find_property(client->dev.of_node, "maxim,slave", NULL))
> +               master = false;
> +
> +       if (!of_property_read_u32(client->dev.of_node, "maxim,refout-load",
> +                                &refout_load))
> +               refout_bits = max2175_refout_load_to_bits(client, refout_load);
> +
> +       clk = devm_clk_get(&client->dev, "xtal");
> +       if (IS_ERR(clk)) {
> +               ret = PTR_ERR(clk);
> +               dev_err(&client->dev, "cannot get xtal clock %d\n", ret);
> +               return -ENODEV;
> +       }
> +
> +       ctx = kzalloc(sizeof(struct max2175_ctx),
> +                            GFP_KERNEL);

devm_kzalloc()?

> +       if (ctx == NULL)
> +               return -ENOMEM;
> +
> +       sd = &ctx->sd;
> +       ctx->master = master;
> +       ctx->mode_resolved = false;
> +
> +       /* Set the defaults */
> +       ctx->freq = bands_rf.rangelow;
> +
> +       ctx->xtal_freq = clk_get_rate(clk);
> +       dev_info(&client->dev, "xtal freq %lluHz\n", ctx->xtal_freq);
> +
> +       v4l2_i2c_subdev_init(sd, client, &max2175_ops);
> +       ctx->client = client;
> +
> +       sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
> +       ctx->dev = dev;
> +
> +       /* Controls */
> +       hdl = &ctx->ctrl_hdl;
> +       ret = v4l2_ctrl_handler_init(hdl, 8);
> +       if (ret) {
> +               dev_err(&client->dev, "ctrl handler init failed\n");
> +               goto err;
> +       }
> +
> +       ctx->lna_gain = v4l2_ctrl_new_std(hdl, &max2175_ctrl_ops,
> +                                         V4L2_CID_RF_TUNER_LNA_GAIN,
> +                                         0, 15, 1, 2);
> +       ctx->lna_gain->flags |= (V4L2_CTRL_FLAG_VOLATILE |
> +                                V4L2_CTRL_FLAG_READ_ONLY);
> +       ctx->if_gain = v4l2_ctrl_new_std(hdl, &max2175_ctrl_ops,
> +                                        V4L2_CID_RF_TUNER_IF_GAIN,
> +                                        0, 31, 1, 0);
> +       ctx->if_gain->flags |= (V4L2_CTRL_FLAG_VOLATILE |
> +                               V4L2_CTRL_FLAG_READ_ONLY);
> +       ctx->pll_lock = v4l2_ctrl_new_std(hdl, &max2175_ctrl_ops,
> +                                         V4L2_CID_RF_TUNER_PLL_LOCK,
> +                                         0, 1, 1, 0);
> +       ctx->pll_lock->flags |= (V4L2_CTRL_FLAG_VOLATILE |
> +                                V4L2_CTRL_FLAG_READ_ONLY);
> +       ctx->i2s_en = v4l2_ctrl_new_custom(hdl, &max2175_i2s_en, NULL);
> +       ctx->i2s_mode = v4l2_ctrl_new_custom(hdl, &max2175_i2s_mode, NULL);
> +       ctx->am_hiz = v4l2_ctrl_new_custom(hdl, &max2175_am_hiz, NULL);
> +       ctx->hsls = v4l2_ctrl_new_custom(hdl, &max2175_hsls, NULL);
> +
> +       if (ctx->xtal_freq == MAX2175_EU_XTAL_FREQ) {
> +               ctx->rx_mode = v4l2_ctrl_new_custom(hdl,
> +                                                   &max2175_eu_rx_mode, NULL);
> +               ctx->rx_modes = (struct max2175_rxmode *)eu_rx_modes;
> +       } else {
> +               ctx->rx_mode = v4l2_ctrl_new_custom(hdl,
> +                                                   &max2175_na_rx_mode, NULL);
> +               ctx->rx_modes = (struct max2175_rxmode *)na_rx_modes;
> +       }

The casts are meant to cast away constness. Can that be avoided?

> --- /dev/null
> +++ b/drivers/media/i2c/max2175/max2175.h

> +/* NOTE: Any addition/deletion in the below enum should be reflected in
> + * V4L2_CID_MAX2175_RX_MODE ctrl strings

Which strings exactly?

> + */
> +enum max2175_modetag {
> +       /* EU modes */
> +       MAX2175_DAB_1_2 = 0,
> +
> +       /* Other possible modes to add in future
> +        * MAX2175_DAB_1_0,
> +        * MAX2175_DAB_1_3,
> +        * MAX2175_EU_FM_2_2,
> +        * MAX2175_EU_FM_1_0,
> +        * MAX2175_EU_FMHD_4_0,
> +        * MAX2175_EU_AM_1_0,
> +        * MAX2175_EU_AM_2_2,
> +        */
> +
> +       /* NA modes */
> +       MAX2175_NA_FM_1_0 = 0,
> +
> +       /* Other possible modes to add in future
> +        * MAX2175_NA_FM_1_2,
> +        * MAX2175_NA_FMHD_1_0,
> +        * MAX2175_NA_FMHD_1_2,
> +        * MAX2175_NA_AM_1_0,
> +        * MAX2175_NA_AM_1_2,
> +        */

The MAX2175_NA_* definitions share their values with the MAX2175_DAB_* and
future MAX2175_EU_* values. Do you have to use a single enum for both?

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
--
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

WARNING: multiple messages have this Message-ID (diff)
From: Geert Uytterhoeven <geert@linux-m68k.org>
To: Ramesh Shanmugasundaram <ramesh.shanmugasundaram@bp.renesas.com>
Cc: Rob Herring <robh+dt@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Mauro Carvalho Chehab <mchehab@kernel.org>,
	Hans Verkuil <hverkuil@xs4all.nl>,
	Sakari Ailus <sakari.ailus@linux.intel.com>,
	Antti Palosaari <crope@iki.fi>,
	Chris Paterson <chris.paterson2@renesas.com>,
	Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
	Linux Media Mailing List <linux-media@vger.kernel.org>,
	"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
	Linux-Renesas <linux-renesas-soc@vger.kernel.org>
Subject: Re: [RFC 1/5] media: i2c: max2175: Add MAX2175 support
Date: Sat, 15 Oct 2016 14:42:18 +0200	[thread overview]
Message-ID: <CAMuHMdUYQoJL4h8prEpontF4YH8Ha+SWDdeZHYEV3_uMZ-SBXw@mail.gmail.com> (raw)
In-Reply-To: <1476281429-27603-2-git-send-email-ramesh.shanmugasundaram@bp.renesas.com>

Hi Ramesh,

On Wed, Oct 12, 2016 at 4:10 PM, Ramesh Shanmugasundaram
<ramesh.shanmugasundaram@bp.renesas.com> 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 < for your patch!amesh.shanmugasundaram@bp.renesas.com>

Thanks for your patch!

> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/i2c/max2175.txt
> @@ -0,0 +1,60 @@
> +Maxim Integrated MAX2175 RF to Bits tuner
> +-----------------------------------------
> +
> +The MAX2175 IC is an advanced analog/digital hybrid-radio receiver with
> +RF to Bits® front-end designed for software-defined radio solutions.
> +
> +Required properties:
> +--------------------
> +- compatible: "maxim,max2175" for MAX2175 RF-to-bits tuner.
> +- clocks: phandle to the fixed xtal clock.
> +- clock-names: name of the fixed xtal clock.
> +- port: video interface child port node of a tuner that defines the local
> +  and remote endpoints. The remote endpoint is assumed to be an SDR device
> +  that is capable of receiving the digital samples from the tuner.
> +
> +Optional properties:
> +--------------------
> +- maxim,slave     : empty property indicates this is a slave of another
> +                    master tuner. This is used to define two tuners in
> +                    diversity mode (1 master, 1 slave). By default each
> +                    tuner is an individual master.
> +- maxim,refout-load: load capacitance value (in pF) on reference output
> +                    drive level. The mapping of these load values to
> +                    respective bit values are given below.
> +                    0 - Reference output disabled
> +                    1 - 10pF load
> +                    2 - 20pF load
> +                    3 - 30pF load
> +                    4 - 40pF load
> +                    5 - 60pF load
> +                    6 - 70pF load

For properties involving units, usually the unit is made part of the
property name, e.g. maxim,refout-load-pF = 40.
This avoids confusion, and allows for extension later.

> +/* A tuner device instance under i2c bus */
> +max2175_0: tuner@60 {
> +       #clock-cells = <0>;
> +       compatible = "maxim,max2175";
> +       reg = <0x60>;
> +       clocks = <&maxim_xtal>;
> +       clock-names = "xtal";
> +       maxim,refout-load = <10>;

10 is not listed above. Perhaps you meant 10 pF?

> --- /dev/null
> +++ b/drivers/media/i2c/max2175/max2175.c
> @@ -0,0 +1,1624 @@

> +/* NOTE: Any addition/deletion in the below list should be reflected in
> + * max2175_modetag enum
> + */

You can drop the above comment if you make this explicit using C99
designated initializers, cfr. below.

> +static const struct max2175_rxmode eu_rx_modes[] = { /* Indexed by EU modetag */
> +       /* EU modes */
> +       { MAX2175_BAND_VHF, 182640000, 0, { 0, 0, 0, 0 } },

[MAX2175_DAB_1_2] = { MAX2175_BAND_VHF, 182640000, 0, { 0, 0, 0, 0 } },

> +};
> +
> +static const struct max2175_rxmode na_rx_modes[] = { /* Indexed by NA modetag */
> +       /* NA modes */
> +       { MAX2175_BAND_FM, 98255520, 1, { 0, 0, 0, 0 } },

[MAX2175_NA_FM_1_0] = { MAX2175_BAND_FM, 98255520, 1, { 0, 0, 0, 0 } },

> +struct max2175_ctx {
> +       struct v4l2_subdev sd;
> +       struct i2c_client *client;
> +       struct device *dev;
> +
> +       /* Cached configuration */
> +       u8 regs[256];
> +       enum max2175_modetag mode;      /* Receive mode tag */
> +       u32 freq;                       /* In Hz */
> +       struct max2175_rxmode *rx_modes;
> +
> +       /* Device settings */
> +       bool master;
> +       u32 decim_ratio;
> +       u64 xtal_freq;
> +
> +       /* ROM values */
> +       u8 rom_bbf_bw_am;
> +       u8 rom_bbf_bw_fm;
> +       u8 rom_bbf_bw_dab;
> +
> +       /* Local copy of old settings */
> +       u8 i2s_test;
> +
> +       u8 nbd_gain;
> +       u8 nbd_threshold;
> +       u8 wbd_gain;
> +       u8 wbd_threshold;
> +       u8 bbd_threshold;
> +       u8 bbdclip_threshold;
> +       u8 lt_wbd_threshold;
> +       u8 lt_wbd_gain;
> +
> +       /* Controls */
> +       struct v4l2_ctrl_handler ctrl_hdl;
> +       struct v4l2_ctrl *lna_gain;     /* LNA gain value */
> +       struct v4l2_ctrl *if_gain;      /* I/F gain value */
> +       struct v4l2_ctrl *pll_lock;     /* PLL lock */
> +       struct v4l2_ctrl *i2s_en;       /* I2S output enable */
> +       struct v4l2_ctrl *i2s_mode;     /* I2S mode value */
> +       struct v4l2_ctrl *am_hiz;       /* AM High impledance input */
> +       struct v4l2_ctrl *hsls;         /* High-side/Low-side polarity */
> +       struct v4l2_ctrl *rx_mode;      /* Receive mode */
> +
> +       /* Driver private variables */
> +       bool mode_resolved;             /* Flag to sanity check settings */
> +};

Sorting the struct members by decreasing size helps to avoid gaps due to
alignment restrictions, and may reduce memory consumption.

> +/* Flush local copy to device from idx to idx+len (inclusive) */
> +static void max2175_flush_regstore(struct max2175_ctx *ctx, u8 idx, u8 len)
> +{
> +       u8 i;

I'd just use unsigned int for loop counters.

> +
> +       for (i = idx; i <= len; i++)
> +               max2175_reg_write(ctx, i, ctx->regs[i]);
> +}

> +static int max2175_update_i2s_mode(struct max2175_ctx *ctx, u32 i2s_mode)
> +{
> +       /* Only change if it's new */
> +       if (max2175_read_bits(ctx, 29, 2, 0) == i2s_mode)

Many magic numbers, not only here (29, 2), but everywhere.
Can you please add #defines for these?

> +               return 0;
> +
> +       max2175_write_bits(ctx, 29, 2, 0, i2s_mode);
> +
> +       /* Based on I2S mode value I2S_WORD_CNT values change */
> +       if (i2s_mode == MAX2175_I2S_MODE3) {
> +               max2175_write_bits(ctx, 30, 6, 0, 1);
> +       } else if (i2s_mode == MAX2175_I2S_MODE2 ||
> +                  i2s_mode == MAX2175_I2S_MODE4) {
> +               max2175_write_bits(ctx, 30, 6, 0, 0);
> +       } else if (i2s_mode == MAX2175_I2S_MODE0) {
> +               max2175_write_bits(ctx, 30, 6, 0,
> +                                  ctx->rx_modes[ctx->mode].i2s_word_size);
> +       } else {
> +               v4l2_err(ctx->client,
> +                        "failed: i2s_mode %u unsupported\n", i2s_mode);
> +               return 1;
> +       }

switch (i2s_mode) { ... }

> +       mxm_dbg(ctx, "updated i2s_mode %u\n", i2s_mode);
> +       return 0;
> +}

> +static void max2175_set_filter_coeffs(struct max2175_ctx *ctx, u8 m_sel,
> +                                     u8 bank, const u16 *coeffs)
> +{
> +       u8 i, coeff_addr, upper_address;

I'd just use unsigned int for these.

> +
> +       mxm_dbg(ctx, "start: m_sel %d bank %d\n", m_sel, bank);
> +       max2175_write_bits(ctx, 114, 5, 4, m_sel);
> +
> +       if (m_sel == 2)
> +               upper_address = 12;
> +       else
> +               upper_address = 24;
> +
> +       max2175_set_bit(ctx, 117, 7, 1);
> +       for (i = 0; i < upper_address; i++) {
> +               coeff_addr = i + (bank * 24);
> +               max2175_set_bits(ctx, 115, 7, 0,
> +                                (u8)((coeffs[i] >> 8) & 0xff));
> +               max2175_set_bits(ctx, 116, 7, 0, (u8)(coeffs[i] & 0xff));

I don't think you need the casts to u8, or the masking with 0xff.

> +               max2175_set_bits(ctx, 117, 6, 0, coeff_addr);
> +               max2175_flush_regstore(ctx, 115, 3);
> +       }
> +       max2175_write_bit(ctx, 117, 7, 0);
> +}
> +
> +static void max2175_load_dab_1p2(struct max2175_ctx *ctx)
> +{
> +       u32 i;

unsigned int?

> +static int max2175_set_lo_freq(struct max2175_ctx *ctx, u64 lo_freq)
> +{
> +       int ret;
> +       u32 lo_mult;
> +       u64 scaled_lo_freq;
> +       const u64 scale_factor = 1000000ULL;
> +       u64 scaled_npf, scaled_integer, scaled_fraction;
> +       u32 frac_desired, int_desired;
> +       u8 loband_bits, vcodiv_bits;
> +
> +       scaled_lo_freq = lo_freq;
> +       /* Scale to larger number for precision */
> +       scaled_lo_freq = scaled_lo_freq * scale_factor * 100;
> +
> +       mxm_dbg(ctx, "scaled lo_freq %llu lo_freq %llu\n",
> +               scaled_lo_freq, lo_freq);
> +
> +       if (MAX2175_IS_BAND_AM(ctx)) {
> +               if (max2175_get_bit(ctx, 5, 7) == 0)
> +                       loband_bits = 0;
> +                       vcodiv_bits = 0;
> +                       lo_mult = 16;
> +       } else if (max2175_get_bits(ctx, 5, 1, 0) == MAX2175_BAND_FM) {
> +               if (lo_freq <= 74700000) {
> +                       loband_bits = 0;
> +                       vcodiv_bits = 0;
> +                       lo_mult = 16;
> +               } else if ((lo_freq > 74700000) && (lo_freq <= 110000000)) {
> +                       loband_bits = 1;
> +                       vcodiv_bits = 0;
> +               } else {
> +                       loband_bits = 1;
> +                       vcodiv_bits = 3;
> +               }
> +               lo_mult = 8;
> +       } else if (max2175_get_bits(ctx, 5, 1, 0) == MAX2175_BAND_VHF) {
> +               if (lo_freq <= 210000000) {
> +                       loband_bits = 2;
> +                       vcodiv_bits = 2;
> +               } else {
> +                       loband_bits = 2;
> +                       vcodiv_bits = 1;
> +               }
> +               lo_mult = 4;
> +       } else {
> +               loband_bits = 3;
> +               vcodiv_bits = 2;
> +               lo_mult = 2;
> +       }
> +
> +       if (max2175_get_bits(ctx, 5, 1, 0) == MAX2175_BAND_L)
> +               scaled_npf = (scaled_lo_freq / ctx->xtal_freq / lo_mult) / 100;
> +       else
> +               scaled_npf = (scaled_lo_freq / ctx->xtal_freq * lo_mult) / 100;

Please use one of the div64*() functions for divisions involving 64-bit
quantities (try to build for 32-bit and see). More of these below...

> +       scaled_integer = scaled_npf / scale_factor * scale_factor;
> +       int_desired = (u32)(scaled_npf / scale_factor);
> +       scaled_fraction = scaled_npf - scaled_integer;
> +       frac_desired = (u32)(scaled_fraction * 1048576 / scale_factor);

> +       /* Write the calculated values to the appropriate registers */
> +       max2175_set_bits(ctx, 5, 3, 2, loband_bits);
> +       max2175_set_bits(ctx, 6, 7, 6, vcodiv_bits);
> +       max2175_set_bits(ctx, 1, 7, 0, (u8)(int_desired & 0xff));
> +       max2175_set_bits(ctx, 2, 3, 0, (u8)((frac_desired >> 16) & 0x1f));
> +       max2175_set_bits(ctx, 3, 7, 0, (u8)((frac_desired >> 8) & 0xff));
> +       max2175_set_bits(ctx, 4, 7, 0, (u8)(frac_desired & 0xff));

No need for casts etc.

> +       /* Flush the above registers to device */
> +       max2175_flush_regstore(ctx, 1, 6);
> +       return ret;
> +}
> +
> +static int max2175_set_nco_freq(struct max2175_ctx *ctx, s64 nco_freq_desired)
> +{
> +       int ret;
> +       u64 clock_rate, abs_nco_freq;
> +       s64  nco_freq, nco_val_desired;
> +       u32 nco_reg;
> +       const u64 scale_factor = 1000000ULL;
> +
> +       mxm_dbg(ctx, "nco_freq: freq = %lld\n", nco_freq_desired);
> +       clock_rate = ctx->xtal_freq / ctx->decim_ratio;
> +       nco_freq = -nco_freq_desired;
> +
> +       if (nco_freq < 0)
> +               abs_nco_freq = -nco_freq;
> +       else
> +               abs_nco_freq = nco_freq;
> +
> +       /* Scale up the values for precision */
> +       if (abs_nco_freq < (clock_rate / 2)) {
> +               nco_val_desired = (2 * nco_freq * scale_factor) / clock_rate;
> +       } else {
> +               if (nco_freq < 0)
> +                       nco_val_desired = (-2 * (clock_rate - abs_nco_freq) *
> +                               scale_factor) / clock_rate;
> +               else
> +                       nco_val_desired = (2 * (clock_rate - abs_nco_freq) *
> +                               scale_factor) / clock_rate;
> +       }
> +
> +       /* Scale down to get the fraction */
> +       if (nco_freq < 0)
> +               nco_reg = 0x200000 + ((nco_val_desired * 1048576) /
> +                                     scale_factor);
> +       else
> +               nco_reg = (nco_val_desired * 1048576) / scale_factor;

More 64-bit divisions. In addition, the dividers are 64-bit too.
Can't they be 32-bit?

> +static int max2175_probe(struct i2c_client *client,
> +                       const struct i2c_device_id *id)
> +{
> +       struct max2175_ctx *ctx;
> +       struct device *dev = &client->dev;
> +       struct v4l2_subdev *sd;
> +       struct v4l2_ctrl_handler *hdl;
> +       struct clk *clk;
> +       bool master = true;
> +       u32 refout_load, refout_bits = 0;       /* REFOUT disabled */
> +       int ret;
> +
> +       /* Check if the adapter supports the needed features */
> +       if (!i2c_check_functionality(client->adapter,
> +                                    I2C_FUNC_SMBUS_BYTE_DATA)) {
> +               dev_err(&client->dev, "i2c check failed\n");
> +               return -EIO;
> +       }
> +
> +       if (of_find_property(client->dev.of_node, "maxim,slave", NULL))
> +               master = false;
> +
> +       if (!of_property_read_u32(client->dev.of_node, "maxim,refout-load",
> +                                &refout_load))
> +               refout_bits = max2175_refout_load_to_bits(client, refout_load);
> +
> +       clk = devm_clk_get(&client->dev, "xtal");
> +       if (IS_ERR(clk)) {
> +               ret = PTR_ERR(clk);
> +               dev_err(&client->dev, "cannot get xtal clock %d\n", ret);
> +               return -ENODEV;
> +       }
> +
> +       ctx = kzalloc(sizeof(struct max2175_ctx),
> +                            GFP_KERNEL);

devm_kzalloc()?

> +       if (ctx == NULL)
> +               return -ENOMEM;
> +
> +       sd = &ctx->sd;
> +       ctx->master = master;
> +       ctx->mode_resolved = false;
> +
> +       /* Set the defaults */
> +       ctx->freq = bands_rf.rangelow;
> +
> +       ctx->xtal_freq = clk_get_rate(clk);
> +       dev_info(&client->dev, "xtal freq %lluHz\n", ctx->xtal_freq);
> +
> +       v4l2_i2c_subdev_init(sd, client, &max2175_ops);
> +       ctx->client = client;
> +
> +       sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
> +       ctx->dev = dev;
> +
> +       /* Controls */
> +       hdl = &ctx->ctrl_hdl;
> +       ret = v4l2_ctrl_handler_init(hdl, 8);
> +       if (ret) {
> +               dev_err(&client->dev, "ctrl handler init failed\n");
> +               goto err;
> +       }
> +
> +       ctx->lna_gain = v4l2_ctrl_new_std(hdl, &max2175_ctrl_ops,
> +                                         V4L2_CID_RF_TUNER_LNA_GAIN,
> +                                         0, 15, 1, 2);
> +       ctx->lna_gain->flags |= (V4L2_CTRL_FLAG_VOLATILE |
> +                                V4L2_CTRL_FLAG_READ_ONLY);
> +       ctx->if_gain = v4l2_ctrl_new_std(hdl, &max2175_ctrl_ops,
> +                                        V4L2_CID_RF_TUNER_IF_GAIN,
> +                                        0, 31, 1, 0);
> +       ctx->if_gain->flags |= (V4L2_CTRL_FLAG_VOLATILE |
> +                               V4L2_CTRL_FLAG_READ_ONLY);
> +       ctx->pll_lock = v4l2_ctrl_new_std(hdl, &max2175_ctrl_ops,
> +                                         V4L2_CID_RF_TUNER_PLL_LOCK,
> +                                         0, 1, 1, 0);
> +       ctx->pll_lock->flags |= (V4L2_CTRL_FLAG_VOLATILE |
> +                                V4L2_CTRL_FLAG_READ_ONLY);
> +       ctx->i2s_en = v4l2_ctrl_new_custom(hdl, &max2175_i2s_en, NULL);
> +       ctx->i2s_mode = v4l2_ctrl_new_custom(hdl, &max2175_i2s_mode, NULL);
> +       ctx->am_hiz = v4l2_ctrl_new_custom(hdl, &max2175_am_hiz, NULL);
> +       ctx->hsls = v4l2_ctrl_new_custom(hdl, &max2175_hsls, NULL);
> +
> +       if (ctx->xtal_freq == MAX2175_EU_XTAL_FREQ) {
> +               ctx->rx_mode = v4l2_ctrl_new_custom(hdl,
> +                                                   &max2175_eu_rx_mode, NULL);
> +               ctx->rx_modes = (struct max2175_rxmode *)eu_rx_modes;
> +       } else {
> +               ctx->rx_mode = v4l2_ctrl_new_custom(hdl,
> +                                                   &max2175_na_rx_mode, NULL);
> +               ctx->rx_modes = (struct max2175_rxmode *)na_rx_modes;
> +       }

The casts are meant to cast away constness. Can that be avoided?

> --- /dev/null
> +++ b/drivers/media/i2c/max2175/max2175.h

> +/* NOTE: Any addition/deletion in the below enum should be reflected in
> + * V4L2_CID_MAX2175_RX_MODE ctrl strings

Which strings exactly?

> + */
> +enum max2175_modetag {
> +       /* EU modes */
> +       MAX2175_DAB_1_2 = 0,
> +
> +       /* Other possible modes to add in future
> +        * MAX2175_DAB_1_0,
> +        * MAX2175_DAB_1_3,
> +        * MAX2175_EU_FM_2_2,
> +        * MAX2175_EU_FM_1_0,
> +        * MAX2175_EU_FMHD_4_0,
> +        * MAX2175_EU_AM_1_0,
> +        * MAX2175_EU_AM_2_2,
> +        */
> +
> +       /* NA modes */
> +       MAX2175_NA_FM_1_0 = 0,
> +
> +       /* Other possible modes to add in future
> +        * MAX2175_NA_FM_1_2,
> +        * MAX2175_NA_FMHD_1_0,
> +        * MAX2175_NA_FMHD_1_2,
> +        * MAX2175_NA_AM_1_0,
> +        * MAX2175_NA_AM_1_2,
> +        */

The MAX2175_NA_* definitions share their values with the MAX2175_DAB_* and
future MAX2175_EU_* values. Do you have to use a single enum for both?

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

  parent reply	other threads:[~2016-10-15 12:42 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-12 14:10 [RFC 0/5] Add V4L2 SDR (DRIF & MAX2175) driver Ramesh Shanmugasundaram
2016-10-12 14:10 ` [RFC 1/5] media: i2c: max2175: Add MAX2175 support Ramesh Shanmugasundaram
     [not found]   ` <1476281429-27603-2-git-send-email-ramesh.shanmugasundaram-kTT6dE0pTRh9uiUsa/gSgQ@public.gmane.org>
2016-10-15 12:42     ` Geert Uytterhoeven [this message]
2016-10-15 12:42       ` Geert Uytterhoeven
     [not found]       ` <CAMuHMdUYQoJL4h8prEpontF4YH8Ha+SWDdeZHYEV3_uMZ-SBXw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2016-10-18 15:04         ` Ramesh Shanmugasundaram
2016-10-18 15:04           ` Ramesh Shanmugasundaram
2016-10-18 19:25   ` Laurent Pinchart
2016-10-21 14:49     ` Ramesh Shanmugasundaram
2016-11-10  8:46       ` Laurent Pinchart
2016-10-12 14:10 ` [RFC 2/5] media: v4l2-ctrls: Reserve controls for MAX217X Ramesh Shanmugasundaram
2016-10-12 14:10 ` [RFC 3/5] media: platform: rcar_drif: Add DRIF support Ramesh Shanmugasundaram
2016-10-18 13:13   ` Rob Herring
2016-10-18 15:13     ` Ramesh Shanmugasundaram
2016-10-18 14:29   ` Geert Uytterhoeven
2016-10-18 18:26     ` Laurent Pinchart
2016-10-21 13:17       ` Ramesh Shanmugasundaram
2016-10-21 13:17         ` Ramesh Shanmugasundaram
     [not found]     ` <CAMuHMdXvGEm3bdNOsa6Q1FLB9yMSTAzO4nHcCb-pnYYwg6f6Cg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2016-10-21 13:15       ` Ramesh Shanmugasundaram
2016-10-21 13:15         ` Ramesh Shanmugasundaram
2016-10-12 14:10 ` [RFC 4/5] media: Add new SDR formats SC16, SC18 & SC20 Ramesh Shanmugasundaram
2016-10-12 14:10 ` [RFC 5/5] doc_rst: media: New " Ramesh Shanmugasundaram
     [not found]   ` <1476281429-27603-6-git-send-email-ramesh.shanmugasundaram-kTT6dE0pTRh9uiUsa/gSgQ@public.gmane.org>
2016-10-18 18:35     ` Laurent Pinchart
2016-10-18 18:35       ` Laurent Pinchart
2016-10-24 10:19       ` Ramesh Shanmugasundaram
2016-11-02  9:00       ` Ramesh Shanmugasundaram
2016-11-02  9:00         ` Ramesh Shanmugasundaram
     [not found]         ` <SG2PR06MB10389152CEC59BB77A5DA7DDC3A00-ESzmfEwOt/zfc7TNChRnj20DtJ1/0DrXvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
2016-11-02 20:58           ` Laurent Pinchart
2016-11-02 20:58             ` Laurent Pinchart
2016-11-03 20:36             ` Antti Palosaari
2016-11-03 20:36               ` Antti Palosaari
2016-11-04  9:23               ` Ramesh Shanmugasundaram
2016-11-10  8:08                 ` Laurent Pinchart
2016-11-11  4:54                   ` Antti Palosaari
2016-11-11 13:53                   ` Hans Verkuil
     [not found]                     ` <8438b944-216e-3237-c312-92a674fd4541-qWit8jRvyhVmR6Xm/wNWPw@public.gmane.org>
2016-11-11 13:57                       ` Laurent Pinchart
2016-11-11 13:57                         ` Laurent Pinchart
2016-11-11 14:00                         ` Hans Verkuil
     [not found]                           ` <fb15b6f3-6c5c-0922-8655-aabd4799d158-qWit8jRvyhVmR6Xm/wNWPw@public.gmane.org>
2016-11-14 15:53                             ` Ramesh Shanmugasundaram
2016-11-14 15:53                               ` 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=CAMuHMdUYQoJL4h8prEpontF4YH8Ha+SWDdeZHYEV3_uMZ-SBXw@mail.gmail.com \
    --to=geert-td1emuhucqxl1znqvxdv9g@public.gmane.org \
    --cc=chris.paterson2-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org \
    --cc=crope-X3B1VOXEql0@public.gmane.org \
    --cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=hverkuil-qWit8jRvyhVmR6Xm/wNWPw@public.gmane.org \
    --cc=laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw@public.gmane.org \
    --cc=linux-media-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=mark.rutland-5wv7dgnIgG8@public.gmane.org \
    --cc=mchehab-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
    --cc=ramesh.shanmugasundaram-kTT6dE0pTRh9uiUsa/gSgQ@public.gmane.org \
    --cc=robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
    --cc=sakari.ailus-VuQAYsv1563Yd54FQh9/CA@public.gmane.org \
    /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.