Message ID | 20240213140240.159057-2-biju.das.jz@bp.renesas.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Sakari Ailus |
Headers |
Received: from ny.mirrors.kernel.org ([147.75.199.223]) by linuxtv.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from <linux-media+bounces-5080-patchwork=linuxtv.org@vger.kernel.org>) id 1rZtNg-0003O2-1V for patchwork@linuxtv.org; Tue, 13 Feb 2024 14:03:28 +0000 Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id 2B37E1C228A4 for <patchwork@linuxtv.org>; Tue, 13 Feb 2024 14:03:27 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id EC8005788F; Tue, 13 Feb 2024 14:02:57 +0000 (UTC) X-Original-To: linux-media@vger.kernel.org Received: from relmlie5.idc.renesas.com (relmlor1.renesas.com [210.160.252.171]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 5AE9A5786B; Tue, 13 Feb 2024 14:02:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.160.252.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707832977; cv=none; b=UZXmYxT327Wlj6Wcp+OYfWaLmsSx2WgaA997K3cxvsH40RbPJgMqkaqUP23rG32vPOEd3xiJVyCxbhNRMJYGcK5WKRiWSavJE33xBBXOJtT+vZju+oeIjxbHUHC6u1DgEiUKgJf/IBYKtdOkj5Q2JgIwpGK2mrpfS2Biwpupts8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707832977; c=relaxed/simple; bh=lERj8IJJn2b3H45H4QY4vrFeJGjaU86NcDG5RsIztMM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=AaLOTfS7l8yizHgHSGWWOeENGm2KSPuzFULd8FY6JxQx4E+5S+KYT3QRrNLSOyWZ+Z9n40Kg2K2V5PXkF5CDFhgn3cyu/RoigK0tSuIHBHcnvehePdk62ysMlCwxwpPTIX7ebMtqAj4BThPlMNc0/s4tCnNu+WsfHA68nIjy0qQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=bp.renesas.com; spf=pass smtp.mailfrom=bp.renesas.com; arc=none smtp.client-ip=210.160.252.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=bp.renesas.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bp.renesas.com X-IronPort-AV: E=Sophos;i="6.06,157,1705330800"; d="scan'208";a="193787617" Received: from unknown (HELO relmlir5.idc.renesas.com) ([10.200.68.151]) by relmlie5.idc.renesas.com with ESMTP; 13 Feb 2024 23:02:48 +0900 Received: from localhost.localdomain (unknown [10.226.93.58]) by relmlir5.idc.renesas.com (Postfix) with ESMTP id 3CF254003EA8; Tue, 13 Feb 2024 23:02:45 +0900 (JST) From: Biju Das <biju.das.jz@bp.renesas.com> To: Sakari Ailus <sakari.ailus@linux.intel.com>, Mauro Carvalho Chehab <mchehab@kernel.org> Cc: Biju Das <biju.das.jz@bp.renesas.com>, linux-media@vger.kernel.org, Geert Uytterhoeven <geert+renesas@glider.be>, Prabhakar Mahadev Lad <prabhakar.mahadev-lad.rj@bp.renesas.com>, Biju Das <biju.das.au@gmail.com>, linux-renesas-soc@vger.kernel.org Subject: [PATCH 1/2] media: i2c: ov5645: Move the register 0x3008 from ov5645_global_init_setting Date: Tue, 13 Feb 2024 14:02:39 +0000 Message-Id: <20240213140240.159057-2-biju.das.jz@bp.renesas.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240213140240.159057-1-biju.das.jz@bp.renesas.com> References: <20240213140240.159057-1-biju.das.jz@bp.renesas.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: <linux-media.vger.kernel.org> List-Subscribe: <mailto:linux-media+subscribe@vger.kernel.org> List-Unsubscribe: <mailto:linux-media+unsubscribe@vger.kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-LSpam-Score: -2.0 (--) X-LSpam-Report: No, score=-2.0 required=5.0 tests=ARC_SIGNED=0.001,ARC_VALID=-0.1,DMARC_NONE=0.898,HEADER_FROM_DIFFERENT_DOMAINS=0.5,MAILING_LIST_MULTI=-1,RCVD_IN_DNSWL_MED=-2.3,SPF_HELO_NONE=0.001,SPF_PASS=-0.001 autolearn=ham autolearn_force=no |
Series |
Fix OV5645 capture issue with 400kHz i2c bus frequency
|
|
Commit Message
Biju Das
Feb. 13, 2024, 2:02 p.m. UTC
Testing OV5645 with i2c bus frequency @400kHz on RZ/G2L SMARC EVL platform
shows issues like the captured image is either greenish or it is not
capturing the image at all. However, It is working ok when the i2c
frequency is 100kHz. From this, it is clear that we have a timing issue
at high speed. The testing also shows that if we add a delay >= 1 msec
after register write {0x3008, 0x82}, then the captured image is always
good. So, move the register 0x3008 and 0x3103 from ov5645_*_init_setting
to a new table ov5645_global_init_setting.
Drop the unnecessary entry { 0x3008, 0x42 } from ov5645_*init_setting
table at the start.
Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
drivers/media/i2c/ov5645.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
Comments
Hi Biju, I couldn't find a datasheet for the OV5645 but the one for OV5642 looked pretty similar when it comes to the issues mentioned here. > Testing OV5645 with i2c bus frequency @400kHz on RZ/G2L SMARC EVL platform > shows issues like the captured image is either greenish or it is not > capturing the image at all. However, It is working ok when the i2c > frequency is 100kHz. From this, it is clear that we have a timing issue > at high speed. The testing also shows that if we add a delay >= 1 msec That could match the "VDD stable to sensor stable" delay in the datasheet. > after register write {0x3008, 0x82}, then the captured image is always > good. So, move the register 0x3008 and 0x3103 from ov5645_*_init_setting > to a new table ov5645_global_init_setting. > > Drop the unnecessary entry { 0x3008, 0x42 } from ov5645_*init_setting > table at the start. It seems this is not needed to fix your issue? Then, this would be a seperate change with a dedicated reason, I'd think. There is another pair of activating power-down mode and immediately disabling it again. Either we simplify it, too, or we leave both in place. Or at least make sure there wasn't a reason for them. I'd just leave them. Rest looks good to me. Happy hacking, Wolfram
Hi Wolfram, Thanks for the feedback. On Tue, Feb 13, 2024 at 10:27 PM Wolfram Sang <wsa@kernel.org> wrote: > > Hi Biju, > > I couldn't find a datasheet for the OV5645 but the one for OV5642 looked > pretty similar when it comes to the issues mentioned here. I don't have the data sheet. I am just debugging with a picoscope. > > > Testing OV5645 with i2c bus frequency @400kHz on RZ/G2L SMARC EVL platform > > shows issues like the captured image is either greenish or it is not > > capturing the image at all. However, It is working ok when the i2c > > frequency is 100kHz. From this, it is clear that we have a timing issue > > at high speed. The testing also shows that if we add a delay >= 1 msec > > That could match the "VDD stable to sensor stable" delay in the > datasheet. I think it is different here. That 1 msec is delay associated with applying hardware power see [1] [1] https://elixir.bootlin.com/linux/latest/source/drivers/media/i2c/ov5645.c#L667 > > > after register write {0x3008, 0x82}, then the captured image is always > > good. So, move the register 0x3008 and 0x3103 from ov5645_*_init_setting > > to a new table ov5645_global_init_setting. > > > > Drop the unnecessary entry { 0x3008, 0x42 } from ov5645_*init_setting > > table at the start. > > It seems this is not needed to fix your issue? Then, this would be a > seperate change with a dedicated reason, I'd think. There is another > pair of activating power-down mode and immediately disabling it again. > Either we simplify it, too, or we leave both in place. Or at least make > sure there wasn't a reason for them. I'd just leave them. My bad. I thought as per [2], there are 2 writes for 0x3008, so I should take out the redundant one. I will restore it. [2] https://patchwork.kernel.org/project/linux-renesas-soc/patch/20240126133116.121981-6-biju.das.jz@bp.renesas.com/#25706558 Cheers, Biju
Hi Biju, > I think it is different here. That 1 msec is delay associated with > applying hardware power see [1] Okay, ack. > I will restore it. Thanks! I had meanwhile another thought. What if we kind of merge the two patches, so the outcome is basically this: In ov5645_set_register_array: If (settings->reg == 0x3008 && settings->val == 0x82) usleep_range(1000, 2000) ? Then, we don't need to split the array and we are also future proof if we ever need to set the reset bit again somewhere else. Bonus points for replacing 0x82 with a define :) What do you think? Happy hacking, Wolfram
Hi Wolfram, Thanks for the feedback. > -----Original Message----- > From: Wolfram Sang <wsa@kernel.org> > Sent: Wednesday, February 14, 2024 8:31 AM > Subject: Re: [PATCH 1/2] media: i2c: ov5645: Move the register 0x3008 from > ov5645_global_init_setting > > Hi Biju, > > > I think it is different here. That 1 msec is delay associated with > > applying hardware power see [1] > > Okay, ack. > > > I will restore it. > > Thanks! > > I had meanwhile another thought. What if we kind of merge the two patches, > so the outcome is basically this: > > In ov5645_set_register_array: > > If (settings->reg == 0x3008 && settings->val == 0x82) > usleep_range(1000, 2000) > > ? > > Then, we don't need to split the array and we are also future proof if we > ever need to set the reset bit again somewhere else. > > Bonus points for replacing 0x82 with a define :) > > What do you think? OK, this will do check for all other registers. But from your power down clue and checking ov5640.c Looks like there are 2 registers changes values after writing. [1] 0x3008, 0x82-->0x80 [2] 0x0601, 0x02-->0x00 I think [1] is soft reset based on ov5640. Since there is a gpio based hardware reset available, we can safely remove soft reset[1] and like ov5640.c, if there is no gpio for reset, then do the soft reset[1]. Then add 1msec delay for power down/up(0x3008: 0x42,0x02) and 0x0601 registers. With this looks like the Camera works ok @400kHz. The plans is to add a u8 variable for delay and enable delays for the above registers and add a check like below static int ov5645_set_register_array(struct ov5645 *ov5645, const struct reg_value *settings, unsigned int num_settings) { unsigned int i; int ret; for (i = 0; i < num_settings; ++i, ++settings) { ret = ov5645_write_reg(ov5645, settings->reg, settings->val); if (ret < 0) return ret; if (settings->delay_ms) usleep_range(1000 * settings->delay_ms, 2 * 1000 * settings->delay_ms); } return 0; } Please share your thoughts on this approach. Cheers, Biju
Hi Biju, On Wed, Feb 14, 2024 at 08:25:16PM +0000, Biju Das wrote: > Hi Wolfram, > > Thanks for the feedback. > > > -----Original Message----- > > From: Wolfram Sang <wsa@kernel.org> > > Sent: Wednesday, February 14, 2024 8:31 AM > > Subject: Re: [PATCH 1/2] media: i2c: ov5645: Move the register 0x3008 from > > ov5645_global_init_setting > > > > Hi Biju, > > > > > I think it is different here. That 1 msec is delay associated with > > > applying hardware power see [1] > > > > Okay, ack. > > > > > I will restore it. > > > > Thanks! > > > > I had meanwhile another thought. What if we kind of merge the two patches, > > so the outcome is basically this: > > > > In ov5645_set_register_array: > > > > If (settings->reg == 0x3008 && settings->val == 0x82) > > usleep_range(1000, 2000) > > > > ? > > > > Then, we don't need to split the array and we are also future proof if we > > ever need to set the reset bit again somewhere else. > > > > Bonus points for replacing 0x82 with a define :) > > > > What do you think? > > > OK, this will do check for all other registers. > > But from your power down clue and checking ov5640.c > Looks like there are 2 registers changes values after writing. > > [1] 0x3008, 0x82-->0x80 > [2] 0x0601, 0x02-->0x00 > > I think [1] is soft reset based on ov5640. Since there is a gpio based > hardware reset available, we can safely remove soft reset[1] and like > ov5640.c, if there is no gpio for reset, then do the soft reset[1]. I guess that would work. My understanding is that hard reset control is mandatory for the device, so there really should be no need for soft reset in the driver. > > > Then add 1msec delay for power down/up(0x3008: 0x42,0x02) and 0x0601 > registers. > > With this looks like the Camera works ok @400kHz. > > The plans is to add a u8 variable for delay and enable delays for the above registers > and add a check like below > > static int ov5645_set_register_array(struct ov5645 *ov5645, > const struct reg_value *settings, > unsigned int num_settings) > { > unsigned int i; > int ret; > > for (i = 0; i < num_settings; ++i, ++settings) { > ret = ov5645_write_reg(ov5645, settings->reg, settings->val); > if (ret < 0) > return ret; > > if (settings->delay_ms) > usleep_range(1000 * settings->delay_ms, 2 * 1000 * settings->delay_ms); I'd prefer checking the register address in the write function instead of this if you really need it. But it seems you don't. > } > > return 0; > } > > Please share your thoughts on this approach. > > Cheers, > Biju
Hi Sakari, Thanks for the feedback. > -----Original Message----- > From: Sakari Ailus <sakari.ailus@linux.intel.com> > Sent: Wednesday, February 14, 2024 8:49 PM > To: Biju Das <biju.das.jz@bp.renesas.com> > Subject: Re: [PATCH 1/2] media: i2c: ov5645: Move the register 0x3008 from > ov5645_global_init_setting > > Hi Biju, > > On Wed, Feb 14, 2024 at 08:25:16PM +0000, Biju Das wrote: > > Hi Wolfram, > > > > Thanks for the feedback. > > > > > -----Original Message----- > > > From: Wolfram Sang <wsa@kernel.org> > > > Sent: Wednesday, February 14, 2024 8:31 AM > > > Subject: Re: [PATCH 1/2] media: i2c: ov5645: Move the register > > > 0x3008 from ov5645_global_init_setting > > > > > > Hi Biju, > > > > > > > I think it is different here. That 1 msec is delay associated with > > > > applying hardware power see [1] > > > > > > Okay, ack. > > > > > > > I will restore it. > > > > > > Thanks! > > > > > > I had meanwhile another thought. What if we kind of merge the two > > > patches, so the outcome is basically this: > > > > > > In ov5645_set_register_array: > > > > > > If (settings->reg == 0x3008 && settings->val == 0x82) > > > usleep_range(1000, 2000) > > > > > > ? > > > > > > Then, we don't need to split the array and we are also future proof > > > if we ever need to set the reset bit again somewhere else. > > > > > > Bonus points for replacing 0x82 with a define :) > > > > > > What do you think? > > > > > > OK, this will do check for all other registers. > > > > But from your power down clue and checking ov5640.c Looks like there > > are 2 registers changes values after writing. > > > > [1] 0x3008, 0x82-->0x80 > > [2] 0x0601, 0x02-->0x00 > > > > I think [1] is soft reset based on ov5640. Since there is a gpio based > > hardware reset available, we can safely remove soft reset[1] and like > > ov5640.c, if there is no gpio for reset, then do the soft reset[1]. > > I guess that would work. My understanding is that hard reset control is > mandatory for the device, so there really should be no need for soft reset > in the driver. OK. > > > > > > > Then add 1msec delay for power down/up(0x3008: 0x42,0x02) and 0x0601 > > registers. > > > > With this looks like the Camera works ok @400kHz. > > > > The plans is to add a u8 variable for delay and enable delays for the > > above registers and add a check like below > > > > static int ov5645_set_register_array(struct ov5645 *ov5645, > > const struct reg_value *settings, > > unsigned int num_settings) > > { > > unsigned int i; > > int ret; > > > > for (i = 0; i < num_settings; ++i, ++settings) { > > ret = ov5645_write_reg(ov5645, settings->reg, settings->val); > > if (ret < 0) > > return ret; > > > > if (settings->delay_ms) > > usleep_range(1000 * settings->delay_ms, 2 * 1000 * > > settings->delay_ms); > > I'd prefer checking the register address in the write function instead of > this if you really need it. But it seems you don't. With delays in powerup/down registers (0x3008 : 0x42,0x02) it is not stable. So, as you and wolfram mentioned will check the register address instead. I will post the patch, after testing on various platforms(RZ/{G2L,G2LC,V2L,G2UL} with 400kHz and 100 kHz Cheers, Biju > > > } > > > > return 0; > > } > > > > Please share your thoughts on this approach. > > > > Cheers, > > Biju > > -- > Regards, > > Sakari Ailus
Hi Sakari, > -----Original Message----- > From: Biju Das > Sent: Wednesday, February 14, 2024 8:55 PM > Subject: RE: [PATCH 1/2] media: i2c: ov5645: Move the register 0x3008 from > ov5645_global_init_setting > > Hi Sakari, > > Thanks for the feedback. > > > -----Original Message----- > > From: Sakari Ailus <sakari.ailus@linux.intel.com> > > Sent: Wednesday, February 14, 2024 8:49 PM > > To: Biju Das <biju.das.jz@bp.renesas.com> > > Subject: Re: [PATCH 1/2] media: i2c: ov5645: Move the register 0x3008 > > from ov5645_global_init_setting > > > > Hi Biju, > > > > On Wed, Feb 14, 2024 at 08:25:16PM +0000, Biju Das wrote: > > > Hi Wolfram, > > > > > > Thanks for the feedback. > > > > > > > -----Original Message----- > > > > From: Wolfram Sang <wsa@kernel.org> > > > > Sent: Wednesday, February 14, 2024 8:31 AM > > > > Subject: Re: [PATCH 1/2] media: i2c: ov5645: Move the register > > > > 0x3008 from ov5645_global_init_setting > > > > > > > > Hi Biju, > > > > > > > > > I think it is different here. That 1 msec is delay associated > > > > > with applying hardware power see [1] > > > > > > > > Okay, ack. > > > > > > > > > I will restore it. > > > > > > > > Thanks! > > > > > > > > I had meanwhile another thought. What if we kind of merge the two > > > > patches, so the outcome is basically this: > > > > > > > > In ov5645_set_register_array: > > > > > > > > If (settings->reg == 0x3008 && settings->val == 0x82) > > > > usleep_range(1000, 2000) > > > > > > > > ? > > > > > > > > Then, we don't need to split the array and we are also future > > > > proof if we ever need to set the reset bit again somewhere else. > > > > > > > > Bonus points for replacing 0x82 with a define :) > > > > > > > > What do you think? > > > > > > > > > OK, this will do check for all other registers. > > > > > > But from your power down clue and checking ov5640.c Looks like there > > > are 2 registers changes values after writing. > > > > > > [1] 0x3008, 0x82-->0x80 > > > [2] 0x0601, 0x02-->0x00 > > > > > > I think [1] is soft reset based on ov5640. Since there is a gpio > > > based hardware reset available, we can safely remove soft reset[1] > > > and like ov5640.c, if there is no gpio for reset, then do the soft > reset[1]. > > > > I guess that would work. My understanding is that hard reset control > > is mandatory for the device, so there really should be no need for > > soft reset in the driver. > > OK. > > > > > > > > > > > > Then add 1msec delay for power down/up(0x3008: 0x42,0x02) and 0x0601 > > > registers. > > > > > > With this looks like the Camera works ok @400kHz. > > > > > > The plans is to add a u8 variable for delay and enable delays for > > > the above registers and add a check like below > > > > > > static int ov5645_set_register_array(struct ov5645 *ov5645, > > > const struct reg_value *settings, > > > unsigned int num_settings) > > > { > > > unsigned int i; > > > int ret; > > > > > > for (i = 0; i < num_settings; ++i, ++settings) { > > > ret = ov5645_write_reg(ov5645, settings->reg, settings->val); > > > if (ret < 0) > > > return ret; > > > > > > if (settings->delay_ms) > > > usleep_range(1000 * settings->delay_ms, 2 * 1000 * > > > settings->delay_ms); > > > > I'd prefer checking the register address in the write function instead > > of this if you really need it. But it seems you don't. > > With delays in powerup/down registers (0x3008 : 0x42,0x02) it is not > stable. Typo: without delays in powerup/down registers (0x3008 : 0x42,0x02) it is not stable. You can see 0x42 followed by 0x02 which is an indication of power down/up procedure. Cheers, Biju
diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c index a26ac11c989d..a5cc959d535e 100644 --- a/drivers/media/i2c/ov5645.c +++ b/drivers/media/i2c/ov5645.c @@ -116,10 +116,12 @@ static inline struct ov5645 *to_ov5645(struct v4l2_subdev *sd) return container_of(sd, struct ov5645, sd); } -static const struct reg_value ov5645_global_init_setting[] = { +static const struct reg_value ov5645_global_reset_setting[] = { { 0x3103, 0x11 }, - { 0x3008, 0x82 }, - { 0x3008, 0x42 }, + { 0x3008, 0x82 } +}; + +static const struct reg_value ov5645_global_init_setting[] = { { 0x3103, 0x03 }, { 0x3503, 0x07 }, { 0x3002, 0x1c }, @@ -671,6 +673,15 @@ static int ov5645_set_power_on(struct device *dev) msleep(20); + ret = ov5645_set_register_array(ov5645, ov5645_global_reset_setting, + ARRAY_SIZE(ov5645_global_reset_setting)); + if (ret < 0) { + dev_err(ov5645->dev, "could not reset\n"); + goto exit; + } + + usleep_range(1000, 2000); + ret = ov5645_set_register_array(ov5645, ov5645_global_init_setting, ARRAY_SIZE(ov5645_global_init_setting)); if (ret < 0) {