From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
To: kieran.bingham@ideasonboard.com
Cc: "Niklas Söderlund" <niklas.soderlund@ragnatech.se>,
"Jacopo Mondi" <jacopo@jmondi.org>,
linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org
Subject: Re: [PATCH 2/3] i2c: adv748x: configure number of lanes used for TXA CSI-2 transmitter
Date: Wed, 19 Sep 2018 01:50:35 +0300 [thread overview]
Message-ID: <2695002.DvEiIvpvj6@avalon> (raw)
In-Reply-To: <eec42c4d-13b1-32c8-9b18-be60a3f9e5a7@ideasonboard.com>
Hi Kieran,
On Tuesday, 18 September 2018 23:35:16 EEST Kieran Bingham wrote:
> On 18/09/18 20:29, Niklas Söderlund wrote:
> > On 2018-09-18 11:13:45 +0100, Kieran Bingham wrote:
> >> On 18/09/18 02:45, Niklas Söderlund wrote:
> >>> The driver fixed the TXA CSI-2 transmitter in 4-lane mode while it could
> >>> operate using 1-, 2- and 4-lanes. Update the driver to support all modes
> >>> the hardware does.
> >>>
> >>> The driver make use of large tables of static register/value writes when
> >>> configuring the hardware, some writing to undocumented registers.
> >>> Instead of creating 3 sets of the register tables for the different
> >>> modes catch when the register containing NUM_LANES[2:0] is written to
> >>> and inject the correct number of lanes.
> >>
> >> Aye aye aye.
> >>
> >> Neat solution to avoid adding more tables - but is it necessary? And I
> >> can't find it easy to overlook the hack value in checking every register
> >> write against a specific value :-(
> >
> > I agree it's not the most obvious nice solution.
> >
> >> Couldn't we create a function called "adv748x_configure_tx_lanes(...)"
> >> or such and just write this value as appropriate after the tables are
> >> written?
> >>
> >> That will then hopefully take us a step towards not needing (as much of)
> >> these tables.
> >
> > This was my starting point :-) But the register is referenced multiple
> > times in the tables and converting the tables to individual register
> > writes turned out such a mess I judged this solution to be less of a
> > maintenance burden. I'm however open to your views on how you would
> > prefer this to be handled. Keep in mind that each row in the register
> > tables needs to be turned into a:
> >
> > /* Write registerx */
> > ret = adv748x_write(...)
> > if (ret)
> >
> > return ret;
>
> Yes, that construct for each register is certainly painful, compared to
> a table...
>
> I wonder if we can be 'clever/naughty' with macros, or perhaps just do a
> best effort set of writes and catch if any fail.. (this also might be a
> bit ugly)
>
> ret |= adv748x_write(A, a);
> ret |= adv748x_write(B, b);
> ret |= adv748x_write(C, c);
> ret |= adv748x_write(D, d);
> if (ret)
> return -EIO;
I'm not very fond of such constructs as it can hide the original error code. I
proposed an alternative in this mail thread. If that ends up adding too much
overhead the above construct could be considered.
> Or - we could programmatically create the tables of registers to write
> in an array, and easily turn the table generation into code which we can
> manipulate without checking errors after each value.
>
> Then the whole table would get written in a single batch...
>
> (Sort of like how we treat the display lists in the VSP1)
We could do that, but my gut feeling is that it would be too complex and over-
engineered.
> I'm not sure how much code that would take yet, or if it will be more or
> less readable :) Needs some thought....
>
> I wonder what Laurent's take on this is ....
Hopefully you're not wondering anymore :-)
> > So the overview of what happens become much harder to read. Other
> > options such as creating copies of the tables and injecting the NUM_LANE
> > value at probe time I feel just hides the behavior even more.
> >
> > Another option I tried was to splice the tables whenever the register in
> > question was referenced. This became hard to read but less lines of
> > code.
> >
> >> However - *I fully understand ordering may be important here* so
> >> actually it looks like we can't write this after writing the table.
> >>
> >> But it does look conveniently early in the tables, so we could split the
> >> tables out and start functionalising them with the information we do
> >> know.
> >
> > I have not tested if ordering is important or not, the documentation we
> > have is just a sequential list of register writes, The register is used
> > in multiple places in the tables making things even more ugly.
>
> yeouch.
>
> > adv748x_power_up_txa_4lane: 3 times, beginning and middle
> > adv748x_power_down_txa_4lane: 1 time, middle
> > adv748x_init_txa_4lane: 3 times, middle and end
> >
> >> I.e. We could have our init function enable the lanes, and handle the
> >> auto DPHY, then write the rest through the tables.
> >
> > If only that where possible :-)
> >
> > I hold off posting v2 until I know how you wish to handle this. To help
> > you make a decision the number of register writes in the tables involved
> >
> > :-)
> >
> > adv748x_power_up_txa_4lane: 11
> > adv748x_power_down_txa_4lane: 5
>
> I feel like the powerup and down, are good targets for converting to
> functions, and merging to support both TXA and TXB (I appreciate this is
> not a five minute job, but something on my wish-list)
>
> > adv748x_init_txa_4lane: ~50
>
> Yes, 50 writes is probably a lot more painful ...
>
> >>> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> >>> ---
> >>>
> >>> drivers/media/i2c/adv748x/adv748x-core.c | 38 +++++++++++++++++++-----
> >>> 1 file changed, 30 insertions(+), 8 deletions(-)
> >>>
> >>> diff --git a/drivers/media/i2c/adv748x/adv748x-core.c
> >>> b/drivers/media/i2c/adv748x/adv748x-core.c index
> >>> a93f8ea89a228474..9a82cdf301bccb41 100644
> >>> --- a/drivers/media/i2c/adv748x/adv748x-core.c
> >>> +++ b/drivers/media/i2c/adv748x/adv748x-core.c
> >>> @@ -207,13 +207,23 @@ static int adv748x_write_regs(struct adv748x_state
> >>> *state,>>>
> >>> const struct adv748x_reg_value *regs)
> >>>
> >>> {
> >>>
> >>> int ret;
> >>>
> >>> + u8 value;
> >>>
> >>> while (regs->page != ADV748X_PAGE_EOR) {
> >>>
> >>> if (regs->page == ADV748X_PAGE_WAIT) {
> >>>
> >>> msleep(regs->value);
> >>>
> >>> } else {
> >>>
> >>> + value = regs->value;
> >>> +
> >>> + /*
> >>> + * Register 0x00 in TXA needs to bei injected with
> >>
> >> s/bei/be/
> >>
> >>> + * the number of CSI-2 lanes used to transmitt.
> >>
> >> s/transmitt/transmit/
> >>
> >>> + */
> >>> + if (regs->page == ADV748X_PAGE_TXA && regs->reg == 0x00)
> >>> + value = (value & ~7) | state->txa.num_lanes;
> >>> +
> >>>
> >>> ret = adv748x_write(state, regs->page, regs->reg,
> >>>
> >>> - regs->value);
> >>> + value);
> >>>
> >>> if (ret < 0) {
> >>>
> >>> adv_err(state,
> >>>
> >>> "Error regs page: 0x%02x reg: 0x%02x\n",
> >>>
> >>> @@ -233,14 +243,18 @@ static int adv748x_write_regs(struct adv748x_state
> >>> *state,>>>
> >>> static const struct adv748x_reg_value adv748x_power_up_txa_4lane[] = {
> >>>
> >>> - {ADV748X_PAGE_TXA, 0x00, 0x84}, /* Enable 4-lane MIPI */
> >>> - {ADV748X_PAGE_TXA, 0x00, 0xa4}, /* Set Auto DPHY Timing */
> >>> + /* NOTE: NUM_LANES[2:0] in TXA register 0x00 is injected on write.
*/
> >>> + {ADV748X_PAGE_TXA, 0x00, 0x80}, /* Enable n-lane MIPI */
> >>> + {ADV748X_PAGE_TXA, 0x00, 0xa0}, /* Set Auto DPHY Timing */
> >>>
> >>> {ADV748X_PAGE_TXA, 0x31, 0x82}, /* ADI Required Write */
> >>> {ADV748X_PAGE_TXA, 0x1e, 0x40}, /* ADI Required Write */
> >>> {ADV748X_PAGE_TXA, 0xda, 0x01}, /* i2c_mipi_pll_en - 1'b1 */
> >>> {ADV748X_PAGE_WAIT, 0x00, 0x02},/* delay 2 */
> >>>
> >>> - {ADV748X_PAGE_TXA, 0x00, 0x24 },/* Power-up CSI-TX */
> >>> +
> >>> + /* NOTE: NUM_LANES[2:0] in TXA register 0x00 is injected on write.
*/
> >>> + {ADV748X_PAGE_TXA, 0x00, 0x20 },/* Power-up CSI-TX */
> >>> +
> >>>
> >>> {ADV748X_PAGE_WAIT, 0x00, 0x01},/* delay 1 */
> >>> {ADV748X_PAGE_TXA, 0xc1, 0x2b}, /* ADI Required Write */
> >>> {ADV748X_PAGE_WAIT, 0x00, 0x01},/* delay 1 */
> >>>
> >>> @@ -253,7 +267,10 @@ static const struct adv748x_reg_value
> >>> adv748x_power_down_txa_4lane[] = {>>>
> >>> {ADV748X_PAGE_TXA, 0x31, 0x82}, /* ADI Required Write */
> >>> {ADV748X_PAGE_TXA, 0x1e, 0x00}, /* ADI Required Write */
> >>>
> >>> - {ADV748X_PAGE_TXA, 0x00, 0x84}, /* Enable 4-lane MIPI */
> >>> +
> >>> + /* NOTE: NUM_LANES[2:0] in TXA register 0x00 is injected on write.
*/
> >>> + {ADV748X_PAGE_TXA, 0x00, 0x80}, /* Enable n-lane MIPI */
> >>
> >> If we're in power down - shouldn't this be "Disable n-lane MIPI */ ??
> >
> > Well the register write enables the lanes. IIRC the comments here come
> > from the register tables text files found in the "documentation".
>
> Isn't the documentation fabulous :-)
>
> "Write these values, don't ask any questions..."
>
> >>> +
> >>>
> >>> {ADV748X_PAGE_TXA, 0xda, 0x01}, /* i2c_mipi_pll_en - 1'b1 */
> >>> {ADV748X_PAGE_TXA, 0xc1, 0x3b}, /* ADI Required Write */
> >>>
> >>> @@ -399,8 +416,10 @@ static const struct adv748x_reg_value
> >>> adv748x_init_txa_4lane[] = {>>>
> >>> /* Outputs Enabled */
> >>> {ADV748X_PAGE_IO, 0x10, 0xa0}, /* Enable 4-lane CSI Tx & Pixel Port
*/
> >>>
> >>> - {ADV748X_PAGE_TXA, 0x00, 0x84}, /* Enable 4-lane MIPI */
> >>> - {ADV748X_PAGE_TXA, 0x00, 0xa4}, /* Set Auto DPHY Timing */
> >>> + /* NOTE: NUM_LANES[2:0] in TXA register 0x00 is injected on write.
*/
> >>> + {ADV748X_PAGE_TXA, 0x00, 0x80}, /* Enable n-lane MIPI */
> >>> + {ADV748X_PAGE_TXA, 0x00, 0xa0}, /* Set Auto DPHY Timing */
> >>> +
> >>>
> >>> {ADV748X_PAGE_TXA, 0xdb, 0x10}, /* ADI Required Write */
> >>> {ADV748X_PAGE_TXA, 0xd6, 0x07}, /* ADI Required Write */
> >>> {ADV748X_PAGE_TXA, 0xc4, 0x0a}, /* ADI Required Write */
> >>>
> >>> @@ -412,7 +431,10 @@ static const struct adv748x_reg_value
> >>> adv748x_init_txa_4lane[] = {>>>
> >>> {ADV748X_PAGE_TXA, 0x1e, 0x40}, /* ADI Required Write */
> >>> {ADV748X_PAGE_TXA, 0xda, 0x01}, /* i2c_mipi_pll_en - 1'b1 */
> >>> {ADV748X_PAGE_WAIT, 0x00, 0x02},/* delay 2 */
> >>>
> >>> - {ADV748X_PAGE_TXA, 0x00, 0x24 },/* Power-up CSI-TX */
> >>> +
> >>> + /* NOTE: NUM_LANES[2:0] in TXA register 0x00 is injected on write.
*/
> >>> + {ADV748X_PAGE_TXA, 0x00, 0x20 },/* Power-up CSI-TX */
> >>> +
> >>>
> >>> {ADV748X_PAGE_WAIT, 0x00, 0x01},/* delay 1 */
> >>> {ADV748X_PAGE_TXA, 0xc1, 0x2b}, /* ADI Required Write */
> >>> {ADV748X_PAGE_WAIT, 0x00, 0x01},/* delay 1 */
--
Regards,
Laurent Pinchart
next prev parent reply other threads:[~2018-09-19 4:25 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-09-18 1:45 [PATCH 0/3] i2c: adv748x: add support for CSI-2 TXA to work in 1-, 2- and 4-lane mode Niklas Söderlund
2018-09-18 1:45 ` [PATCH 1/3] i2c: adv748x: store number of CSI-2 lanes described in device tree Niklas Söderlund
2018-09-18 10:16 ` Laurent Pinchart
2018-09-18 10:19 ` Kieran Bingham
2018-09-18 10:28 ` Laurent Pinchart
2018-09-18 10:37 ` Kieran Bingham
2018-09-18 10:46 ` Laurent Pinchart
2018-09-18 10:51 ` Kieran Bingham
2018-09-18 11:13 ` Laurent Pinchart
2018-09-20 23:43 ` Sakari Ailus
2018-09-21 9:33 ` Dave Stevenson
2018-09-21 10:01 ` Laurent Pinchart
2018-09-21 12:03 ` Sakari Ailus
2018-09-21 13:46 ` Dave Stevenson
2018-11-13 9:40 ` Sakari Ailus
2018-09-21 13:38 ` Dave Stevenson
2018-09-18 19:06 ` Niklas Söderlund
2018-09-18 1:45 ` [PATCH 2/3] i2c: adv748x: configure number of lanes used for TXA CSI-2 transmitter Niklas Söderlund
2018-09-18 10:13 ` Kieran Bingham
2018-09-18 19:29 ` Niklas Söderlund
2018-09-18 20:35 ` Kieran Bingham
2018-09-18 22:50 ` Laurent Pinchart [this message]
2018-09-18 22:46 ` Laurent Pinchart
2018-09-18 1:45 ` [PATCH 3/3] i2c: adv748x: fix typo in comment for TXB CSI-2 transmitter power down Niklas Söderlund
2018-09-18 9:10 ` Sergei Shtylyov
2018-09-18 9:54 ` Kieran Bingham
2018-09-18 10:22 ` Kieran Bingham
2018-09-18 12:34 ` jacopo mondi
2018-09-18 16:06 ` Kieran Bingham
2018-09-18 10:17 ` Laurent Pinchart
2018-09-26 13:49 ` Kieran Bingham
2018-09-26 14:09 ` Niklas Söderlund
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=2695002.DvEiIvpvj6@avalon \
--to=laurent.pinchart@ideasonboard.com \
--cc=jacopo@jmondi.org \
--cc=kieran.bingham@ideasonboard.com \
--cc=linux-media@vger.kernel.org \
--cc=linux-renesas-soc@vger.kernel.org \
--cc=niklas.soderlund@ragnatech.se \
/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