All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
To: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Manivannan Sadhasivam <mani@kernel.org>,
	Mauro Carvalho Chehab <mchehab@kernel.org>,
	linux-media@vger.kernel.org
Subject: Re: [PATCH 10/11] media: i2c: imx290: Add support for 74.25MHz external clock
Date: Fri, 3 Feb 2023 17:04:13 +0000	[thread overview]
Message-ID: <CAPY8ntC1xAYRUPcDoCLJPjBX+i6Pqgdk7tWazzuVpHq3iF4MqQ@mail.gmail.com> (raw)
In-Reply-To: <Y9wzK0X3witiumpu@pendragon.ideasonboard.com>

Hi Laurent

On Thu, 2 Feb 2023 at 22:03, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
>
> Hi Dave,
>
> Thank you for the patch.
>
> On Tue, Jan 31, 2023 at 07:20:15PM +0000, Dave Stevenson wrote:
> > The sensor supports either a 37.125 or 74.25MHz external, but
> > the driver only supported 37.125MHz.
> >
> > Add the relevant register configuration for either clock
> > frequency option.
> >
> > Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
> > ---
> >  drivers/media/i2c/imx290.c | 120 +++++++++++++++++++++++++++++++------
> >  1 file changed, 103 insertions(+), 17 deletions(-)
> >
> > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > index 5202ef3cc3e6..7f6746f74040 100644
> > --- a/drivers/media/i2c/imx290.c
> > +++ b/drivers/media/i2c/imx290.c
> > @@ -102,6 +102,7 @@
> >  #define IMX290_TCLKPREPARE                           IMX290_REG_16BIT(0x3452)
> >  #define IMX290_TLPX                                  IMX290_REG_16BIT(0x3454)
> >  #define IMX290_X_OUT_SIZE                            IMX290_REG_16BIT(0x3472)
> > +#define IMX290_INCKSEL7                                      IMX290_REG_8BIT(0x3480)
> >
> >  #define IMX290_PGCTRL_REGEN                          BIT(0)
> >  #define IMX290_PGCTRL_THRU                           BIT(1)
> > @@ -159,11 +160,27 @@
> >
> >  #define IMX290_NUM_SUPPLIES                          3
> >
> > +#define CLK_37_125   0
> > +#define CLK_74_25    1
> > +#define NUM_CLK              2
>
> Please add an IMX290 prefer to avoid future namespace clashes.
>
> > +
> >  struct imx290_regval {
> >       u32 reg;
> >       u32 val;
> >  };
> >
> > +/*
> > + * Clock configuration for registers INCKSEL1 to INCKSEL6.
> > + */
> > +struct imx290_clk_cfg {
> > +     u8 incksel1;
> > +     u8 incksel2;
> > +     u8 incksel3;
> > +     u8 incksel4;
> > +     u8 incksel5;
> > +     u8 incksel6;
> > +};
> > +
> >  struct imx290_mode {
> >       u32 width;
> >       u32 height;
> > @@ -173,6 +190,8 @@ struct imx290_mode {
> >
> >       const struct imx290_regval *data;
> >       u32 data_size;
> > +
> > +     const struct imx290_clk_cfg *clk_cfg;
> >  };
> >
> >  struct imx290_csi_cfg {
> > @@ -191,6 +210,7 @@ struct imx290 {
> >       struct device *dev;
> >       struct clk *xclk;
> >       struct regmap *regmap;
> > +     u32 xclk_freq;
> >       u8 nlanes;
> >       u8 mono;
> >
> > @@ -219,7 +239,6 @@ static inline struct imx290 *to_imx290(struct v4l2_subdev *_sd)
> >   */
> >
> >  static const struct imx290_regval imx290_global_init_settings[] = {
> > -     { IMX290_EXTCK_FREQ, 0x2520 },
> >       { IMX290_WINWV_OB, 12 },
> >       { IMX290_WINPH, 0 },
> >       { IMX290_WINPV, 0 },
> > @@ -269,7 +288,16 @@ static const struct imx290_regval imx290_global_init_settings[] = {
> >       { IMX290_REG_8BIT(0x33b0), 0x50 },
> >       { IMX290_REG_8BIT(0x33b2), 0x1a },
> >       { IMX290_REG_8BIT(0x33b3), 0x04 },
> > -     { IMX290_REG_8BIT(0x3480), 0x49 },
>
> One less unnamed register, only 42 to go :-D
>
> > +};
> > +
> > +static const struct imx290_regval imx290_37_125mhz_clock[] = {
> > +     { IMX290_EXTCK_FREQ, 0x2520 },
> > +     { IMX290_INCKSEL7, 0x49 },
> > +};
> > +
> > +static const struct imx290_regval imx290_74_25mhz_clock[] = {
> > +     { IMX290_EXTCK_FREQ, 0x4a40 },
> > +     { IMX290_INCKSEL7, 0x92 },
> >  };
>
> Those two arrays are not used, which I assume is not normal :-) A rebase
> problem maybe ?

Whoops! Seeing as I'd tested at both xclk_freqs it shows how little they do!

> How about moving the INCKSEL7 value to the imx290_clk_cfg structure for
> consistency ?

These two only vary based on xclk_freq, whilst imx290_clk_cfg varies
with mode and xclk. I kept them separate to make that distinction
obvious, rather than duplicating the values between 1080p and 720p
tables.

> >
> >  static const struct imx290_regval imx290_1080p_settings[] = {
> > @@ -279,12 +307,6 @@ static const struct imx290_regval imx290_1080p_settings[] = {
> >       { IMX290_OPB_SIZE_V, 10 },
> >       { IMX290_X_OUT_SIZE, 1920 },
> >       { IMX290_Y_OUT_SIZE, 1080 },
> > -     { IMX290_INCKSEL1, 0x18 },
> > -     { IMX290_INCKSEL2, 0x03 },
> > -     { IMX290_INCKSEL3, 0x20 },
> > -     { IMX290_INCKSEL4, 0x01 },
> > -     { IMX290_INCKSEL5, 0x1a },
> > -     { IMX290_INCKSEL6, 0x1a },
> >  };
> >
> >  static const struct imx290_regval imx290_720p_settings[] = {
> > @@ -294,12 +316,6 @@ static const struct imx290_regval imx290_720p_settings[] = {
> >       { IMX290_OPB_SIZE_V, 4 },
> >       { IMX290_X_OUT_SIZE, 1280 },
> >       { IMX290_Y_OUT_SIZE, 720 },
> > -     { IMX290_INCKSEL1, 0x20 },
> > -     { IMX290_INCKSEL2, 0x00 },
> > -     { IMX290_INCKSEL3, 0x20 },
> > -     { IMX290_INCKSEL4, 0x01 },
> > -     { IMX290_INCKSEL5, 0x1a },
> > -     { IMX290_INCKSEL6, 0x1a },
> >  };
> >
> >  static const struct imx290_regval imx290_10bit_settings[] = {
> > @@ -405,6 +421,48 @@ static inline int imx290_link_freqs_num(const struct imx290 *imx290)
> >               return ARRAY_SIZE(imx290_link_freq_4lanes);
> >  }
> >
> > +static const struct imx290_clk_cfg imx290_1080p_clock_config[NUM_CLK] = {
> > +     [CLK_37_125] = {
> > +             /* 37.125MHz clock config */
> > +             .incksel1 = 0x18,
> > +             .incksel2 = 0x03,
> > +             .incksel3 = 0x20,
> > +             .incksel4 = 0x01,
> > +             .incksel5 = 0x1a,
> > +             .incksel6 = 0x1a,
> > +     },
>
> As the incksel[0-6] fields are only used in one place, to write all 6 of
> them to the device, you could also drop the imx290_clk_cfg structure and
> turn this into a imx290_regval array. Entirely up to you.

If you make them an array of imx290_regval then you also need to
manage the length of those arrays and either maintain that separately
for each one, or try and insert a compile time assert to pick up the
mismatch.
At least a dedicated struct avoids that pitfall.

> > +     [CLK_74_25] = {
> > +             /* 74.25MHz clock config */
> > +             .incksel1 = 0x0c,
> > +             .incksel2 = 0x03,
> > +             .incksel3 = 0x10,
> > +             .incksel4 = 0x01,
> > +             .incksel5 = 0x1b,
> > +             .incksel6 = 0x1b,
> > +     },
> > +};
> > +
> > +static const struct imx290_clk_cfg imx290_720p_clock_config[NUM_CLK] = {
> > +     [CLK_37_125] = {
> > +             /* 37.125MHz clock config */
> > +             .incksel1 = 0x20,
> > +             .incksel2 = 0x00,
> > +             .incksel3 = 0x20,
> > +             .incksel4 = 0x01,
> > +             .incksel5 = 0x1a,
> > +             .incksel6 = 0x1a,
> > +     },
> > +     [CLK_74_25] = {
> > +             /* 74.25MHz clock config */
> > +             .incksel1 = 0x10,
> > +             .incksel2 = 0x00,
> > +             .incksel3 = 0x10,
> > +             .incksel4 = 0x01,
> > +             .incksel5 = 0x1b,
> > +             .incksel6 = 0x1b,
> > +     },
> > +};
> > +
> >  /* Mode configs */
> >  static const struct imx290_mode imx290_modes_2lanes[] = {
> >       {
> > @@ -415,6 +473,7 @@ static const struct imx290_mode imx290_modes_2lanes[] = {
> >               .link_freq_index = FREQ_INDEX_1080P,
> >               .data = imx290_1080p_settings,
> >               .data_size = ARRAY_SIZE(imx290_1080p_settings),
> > +             .clk_cfg = imx290_1080p_clock_config,
> >       },
> >       {
> >               .width = 1280,
> > @@ -424,6 +483,7 @@ static const struct imx290_mode imx290_modes_2lanes[] = {
> >               .link_freq_index = FREQ_INDEX_720P,
> >               .data = imx290_720p_settings,
> >               .data_size = ARRAY_SIZE(imx290_720p_settings),
> > +             .clk_cfg = imx290_720p_clock_config,
> >       },
> >  };
> >
> > @@ -436,6 +496,7 @@ static const struct imx290_mode imx290_modes_4lanes[] = {
> >               .link_freq_index = FREQ_INDEX_1080P,
> >               .data = imx290_1080p_settings,
> >               .data_size = ARRAY_SIZE(imx290_1080p_settings),
> > +             .clk_cfg = imx290_1080p_clock_config,
> >       },
> >       {
> >               .width = 1280,
> > @@ -445,6 +506,7 @@ static const struct imx290_mode imx290_modes_4lanes[] = {
> >               .link_freq_index = FREQ_INDEX_720P,
> >               .data = imx290_720p_settings,
> >               .data_size = ARRAY_SIZE(imx290_720p_settings),
> > +             .clk_cfg = imx290_720p_clock_config,
> >       },
> >  };
> >
> > @@ -563,6 +625,23 @@ static int imx290_set_register_array(struct imx290 *imx290,
> >       return 0;
> >  }
> >
> > +static int imx290_set_clock(struct imx290 *imx290)
> > +{
> > +     int clk_idx = (imx290->xclk_freq == 37125000) ? 0 : 1;
> > +     const struct imx290_mode *mode = imx290->current_mode;
> > +     const struct imx290_clk_cfg *clk_cfg = &mode->clk_cfg[clk_idx];
> > +     int ret = 0;
>
> How about turning the clock freq macros into an enum:
>
> enum imx290_clk_freq {
>         IMX290_CLK_37_125 = 0,
>         IMX290_CLK_74_25 = 1,
> };
>
> and replacing in struct imx290
>
> -       u32 xclk_freq;
> +       enum imx290_clk_freq xclk_freq;
>
> ? Then you could could simply write
>
>         const struct imx290_clk_cfg *clk_cfg = &mode->clk_cfg[imx290->xclk_freq];
>
> (you could also name the field xclk_freq_idx if desired). Up to you, if
> you find that messier you can ignore the comment.

Done. Renamed to xclk_idx to make it clear that it's an index.

  Dave

> > +
> > +     imx290_write(imx290, IMX290_INCKSEL1, clk_cfg->incksel1, &ret);
> > +     imx290_write(imx290, IMX290_INCKSEL2, clk_cfg->incksel2, &ret);
> > +     imx290_write(imx290, IMX290_INCKSEL3, clk_cfg->incksel3, &ret);
> > +     imx290_write(imx290, IMX290_INCKSEL4, clk_cfg->incksel4, &ret);
> > +     imx290_write(imx290, IMX290_INCKSEL5, clk_cfg->incksel5, &ret);
> > +     imx290_write(imx290, IMX290_INCKSEL6, clk_cfg->incksel6, &ret);
> > +
> > +     return ret;
> > +}
> > +
> >  static int imx290_set_data_lanes(struct imx290 *imx290)
> >  {
> >       int ret = 0;
> > @@ -863,6 +942,13 @@ static int imx290_start_streaming(struct imx290 *imx290,
> >               return ret;
> >       }
> >
> > +     /* Set clock parameters based on mode and xclk */
> > +     ret = imx290_set_clock(imx290);
> > +     if (ret < 0) {
> > +             dev_err(imx290->dev, "Could not set clocks\n");
> > +             return ret;
> > +     }
> > +
> >       /* Set data lane count */
> >       ret = imx290_set_data_lanes(imx290);
> >       if (ret < 0) {
> > @@ -1259,14 +1345,14 @@ static int imx290_init_clk(struct imx290 *imx290)
> >       int ret;
> >
> >       ret = fwnode_property_read_u32(dev_fwnode(imx290->dev),
> > -                                    "clock-frequency", &xclk_freq);
> > +                                    "clock-frequency", &imx290->xclk_freq);
> >       if (ret) {
> >               dev_err(imx290->dev, "Could not get xclk frequency\n");
> >               return ret;
> >       }
> >
> > -     /* external clock must be 37.125 MHz */
> > -     if (xclk_freq != 37125000) {
> > +     /* external clock must be 37.125 MHz or 74.25MHz */
> > +     if (imx290->xclk_freq != 37125000 && imx290->xclk_freq != 74250000) {
> >               dev_err(imx290->dev, "External clock frequency %u is not supported\n",
> >                       xclk_freq);
> >               return -EINVAL;
>
> --
> Regards,
>
> Laurent Pinchart

  reply	other threads:[~2023-02-03 17:04 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-31 19:20 [PATCH 00/11] imx290: Minor fixes, support for alternate INCK, and more ctrls Dave Stevenson
2023-01-31 19:20 ` [PATCH 01/11] media: i2c: imx290: Match kernel coding style on whitespace Dave Stevenson
2023-02-02  0:21   ` Laurent Pinchart
2023-01-31 19:20 ` [PATCH 02/11] media: i2c: imx290: Set the colorspace fields in the format Dave Stevenson
2023-02-02  0:29   ` Laurent Pinchart
2023-01-31 19:20 ` [PATCH 03/11] media: i2c: imx290: Add V4L2_SUBDEV_FL_HAS_EVENTS and subscribe hooks Dave Stevenson
2023-02-02  0:29   ` Laurent Pinchart
2023-02-03  8:54   ` Alexander Stein
2023-01-31 19:20 ` [PATCH 04/11] media: i2c: imx290: Fix the pixel rate at 148.5Mpix/s Dave Stevenson
2023-02-02  8:13   ` Laurent Pinchart
2023-01-31 19:20 ` [PATCH 05/11] media: i2c: imx290: Support 60fps in 2 lane operation Dave Stevenson
2023-02-02 10:50   ` Laurent Pinchart
2023-02-03  8:50   ` Alexander Stein
2023-01-31 19:20 ` [PATCH 06/11] media: i2c: imx290: Use CSI timings as per datasheet Dave Stevenson
2023-02-02 14:36   ` Laurent Pinchart
2023-02-03  8:04   ` Alexander Stein
2023-02-03  9:09     ` Dave Stevenson
2023-01-31 19:20 ` [PATCH 07/11] media: i2c: imx290: Convert V4L2_CID_HBLANK to read/write Dave Stevenson
2023-02-02 14:58   ` Laurent Pinchart
2023-02-02 15:48     ` Dave Stevenson
2023-02-02 22:14       ` Laurent Pinchart
2023-02-03  7:19   ` Alexander Stein
2023-02-03  8:05     ` Dave Stevenson
2023-02-03  8:39       ` Alexander Stein
2023-01-31 19:20 ` [PATCH 08/11] media: i2c: imx290: Convert V4L2_CID_VBLANK " Dave Stevenson
2023-02-02 15:40   ` Alexander Stein
2023-02-02 16:04     ` Dave Stevenson
2023-02-02 17:42       ` Dave Stevenson
2023-02-03  7:16         ` Alexander Stein
2023-02-02 16:01   ` Laurent Pinchart
2023-01-31 19:20 ` [PATCH 09/11] media: i2c: imx290: Remove duplicated write to IMX290_CTRL_07 Dave Stevenson
2023-02-02 16:04   ` Laurent Pinchart
2023-02-03  7:45   ` Alexander Stein
2023-01-31 19:20 ` [PATCH 10/11] media: i2c: imx290: Add support for 74.25MHz external clock Dave Stevenson
2023-02-02 22:03   ` Laurent Pinchart
2023-02-03 17:04     ` Dave Stevenson [this message]
2023-02-03 18:04       ` Laurent Pinchart
2023-02-03  7:44   ` Alexander Stein
2023-02-03  8:59     ` Laurent Pinchart
2023-02-03  9:30       ` Dave Stevenson
2023-01-31 19:20 ` [PATCH 11/11] media: i2c: imx290: Add support for H & V Flips Dave Stevenson
2023-02-02 22:10   ` Laurent Pinchart
2023-02-03 10:21     ` Dave Stevenson
2023-02-03 18:01       ` Laurent Pinchart
2023-02-03  7:35   ` Alexander Stein
2023-02-03  7:57     ` Dave Stevenson
2023-02-03  8:33       ` Alexander Stein
2023-02-03  9:47         ` Dave Stevenson
2023-02-02 22:16 ` [PATCH 00/11] imx290: Minor fixes, support for alternate INCK, and more ctrls Laurent Pinchart

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=CAPY8ntC1xAYRUPcDoCLJPjBX+i6Pqgdk7tWazzuVpHq3iF4MqQ@mail.gmail.com \
    --to=dave.stevenson@raspberrypi.com \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linux-media@vger.kernel.org \
    --cc=mani@kernel.org \
    --cc=mchehab@kernel.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.