public inbox for linux-media@vger.kernel.org
 help / color / mirror / Atom feed
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

  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