All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stanimir Varbanov <stanimir.varbanov@linaro.org>
To: Todor Tomov <todor.tomov@linaro.org>,
	robh+dt@kernel.org, pawel.moll@arm.com, mark.rutland@arm.com,
	ijc+devicetree@hellion.org.uk, galak@codeaurora.org,
	devicetree@vger.kernel.org, mchehab@osg.samsung.com,
	hverkuil@xs4all.nl, geert@linux-m68k.org, matrandg@cisco.com,
	linux-media@vger.kernel.org
Cc: laurent.pinchart@ideasonboard.com
Subject: Re: [PATCH v2 2/2] media: Add a driver for the ov5645 camera sensor.
Date: Fri, 20 May 2016 18:20:17 +0300	[thread overview]
Message-ID: <573F2B31.1070807@linaro.org> (raw)
In-Reply-To: <1463572208-8826-3-git-send-email-todor.tomov@linaro.org>

Hi Todor,

Thanks for the patch, few comments below.

On 05/18/2016 02:50 PM, Todor Tomov wrote:
> The ov5645 sensor from Omnivision supports up to 2592x1944
> and CSI2 interface.
> 
> The driver adds support for the following modes:
> - 1280x960
> - 1920x1080
> - 2592x1944
> 
> Output format is packed 8bit UYVY.
> 
> Signed-off-by: Todor Tomov <todor.tomov@linaro.org>
> ---
>  drivers/media/i2c/Kconfig  |   11 +
>  drivers/media/i2c/Makefile |    1 +
>  drivers/media/i2c/ov5645.c | 1425 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 1437 insertions(+)
>  create mode 100644 drivers/media/i2c/ov5645.c
> 
> diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
> index 521bbf1..aa17eba 100644
> --- a/drivers/media/i2c/Kconfig
> +++ b/drivers/media/i2c/Kconfig
> @@ -490,6 +490,17 @@ config VIDEO_OV2659
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called ov2659.
>  
> +config VIDEO_OV5645
> +	tristate "OmniVision OV5645 sensor support"
> +	depends on I2C && VIDEO_V4L2
> +	depends on MEDIA_CAMERA_SUPPORT

depends on OF ?

<cut>

> +
> +struct ov5645 {
> +	struct i2c_client *i2c_client;
> +	struct device *dev;
> +	struct v4l2_subdev sd;
> +	struct media_pad pad;
> +	struct v4l2_of_endpoint ep;
> +	struct v4l2_mbus_framefmt fmt;
> +	struct v4l2_rect crop;
> +	struct clk *xclk;
> +	u32 xclk_freq;

this become unused?

> +
> +	struct regulator *io_regulator;
> +	struct regulator *core_regulator;
> +	struct regulator *analog_regulator;
> +
> +	enum ov5645_mode current_mode;
> +
> +	/* Cached control values */
> +	struct v4l2_ctrl_handler ctrls;
> +	struct v4l2_ctrl *saturation;
> +	struct v4l2_ctrl *hflip;
> +	struct v4l2_ctrl *vflip;
> +	struct v4l2_ctrl *autogain;
> +	struct v4l2_ctrl *autoexposure;
> +	struct v4l2_ctrl *awb;
> +	struct v4l2_ctrl *pattern;
> +
> +	struct mutex power_lock; /* lock to protect power state */
> +	int power;
> +
> +	struct gpio_desc *pwdn_gpio;
> +	struct gpio_desc *rst_gpio;
> +};
> +
> +static inline struct ov5645 *to_ov5645(struct v4l2_subdev *sd)
> +{
> +	return container_of(sd, struct ov5645, sd);
> +}

<cut>

> +static int ov5645_s_power(struct v4l2_subdev *sd, int on)
> +{
> +	struct ov5645 *ov5645 = to_ov5645(sd);
> +	int ret = 0;
> +
> +	dev_dbg(ov5645->dev, "%s: on = %d\n", __func__, on);
> +
> +	mutex_lock(&ov5645->power_lock);
> +
> +	/* If the power count is modified from 0 to != 0 or from != 0 to 0,
> +	 * update the power state.
> +	 */
> +	if (ov5645->power == !on) {
> +		if (on) {
> +			ret = ov5645_set_power_on(ov5645);
> +			if (ret < 0) {
> +				dev_err(ov5645->dev, "could not set power %s\n",
> +					on ? "on" : "off");
> +				goto exit;
> +			}
> +
> +			ret = ov5645_init(ov5645);
> +			if (ret < 0) {
> +				dev_err(ov5645->dev,
> +					"could not set init registers\n");
> +				goto exit;
> +			}
> +
> +			ov5645_write_reg(ov5645, OV5645_SYSTEM_CTRL0,
> +					 OV5645_SYSTEM_CTRL0_STOP);

please check the error code.

> +		} else {
> +			ov5645_set_power_off(ov5645);
> +		}
> +
> +		/* Update the power count. */
> +		ov5645->power += on ? 1 : -1;
> +		WARN_ON(ov5645->power < 0);
> +	}
> +
> +exit:
> +	mutex_unlock(&ov5645->power_lock);
> +
> +	return ret;
> +}
> +

<cut>

> +
> +static int ov5645_registered(struct v4l2_subdev *subdev)
> +{
> +	struct i2c_client *client = v4l2_get_subdevdata(subdev);
> +	struct ov5645 *ov5645 = to_ov5645(subdev);
> +	u8 chip_id_high, chip_id_low;
> +	int ret;
> +
> +	ov5645_s_power(&ov5645->sd, true);

check for error here and on the other places where call s_power.

> +
> +	ret = ov5645_read_reg(ov5645, OV5645_CHIP_ID_HIGH_REG, &chip_id_high);
> +	if (ret < 0 || chip_id_high != OV5645_CHIP_ID_HIGH) {
> +		dev_err(ov5645->dev, "could not read ID high\n");
> +		ret = -ENODEV;
> +		goto reg_power_off;
> +	}
> +	ret = ov5645_read_reg(ov5645, OV5645_CHIP_ID_LOW_REG, &chip_id_low);
> +	if (ret < 0 || chip_id_low != OV5645_CHIP_ID_LOW) {
> +		dev_err(ov5645->dev, "could not read ID low\n");
> +		ret = -ENODEV;
> +		goto reg_power_off;
> +	}
> +
> +	dev_info(&client->dev, "OV5645 detected at address 0x%02x\n",
> +		 client->addr);
> +
> +	ov5645_s_power(&ov5645->sd, false);
> +
> +	return 0;
> +
> +reg_power_off:
> +	ov5645_s_power(&ov5645->sd, false);
> +	return ret;
> +}
> +
> +static int ov5645_s_stream(struct v4l2_subdev *subdev, int enable)
> +{
> +	struct ov5645 *ov5645 = to_ov5645(subdev);
> +	int ret;
> +
> +	dev_dbg(ov5645->dev, "%s: enable = %d\n", __func__, enable);
> +
> +	if (enable) {
> +		ret = ov5645_change_mode(ov5645, ov5645->current_mode);
> +		if (ret < 0) {
> +			dev_err(ov5645->dev, "could not set mode %d\n",
> +				ov5645->current_mode);
> +			return ret;
> +		}
> +		ret = v4l2_ctrl_handler_setup(&ov5645->ctrls);
> +		if (ret < 0) {
> +			dev_err(ov5645->dev, "could not sync v4l2 controls\n");
> +			return ret;
> +		}
> +		ov5645_write_reg(ov5645, OV5645_SYSTEM_CTRL0,
> +				 OV5645_SYSTEM_CTRL0_START);

Error code check here and below.

> +	} else {
> +		ov5645_write_reg(ov5645, OV5645_SYSTEM_CTRL0,
> +				 OV5645_SYSTEM_CTRL0_STOP);
> +	}
> +
> +	return 0;
> +}

<cut>

> +static int ov5645_probe(struct i2c_client *client,
> +			const struct i2c_device_id *id)
> +{
> +	struct device *dev = &client->dev;
> +	struct device_node *endpoint;
> +	struct ov5645 *ov5645;
> +	int ret = 0;

no need to initialize

<cut>

> +
> +	ov5645->io_regulator = devm_regulator_get(dev, "dovdd");
> +	if (IS_ERR(ov5645->io_regulator)) {
> +		switch(PTR_ERR(ov5645->io_regulator)) {
> +		case -ENODEV:
> +			/* Regulator is optional so this is ok - continue */

if the regulator is optional then use devm_regulator_get_optional, thus
you can avoid checking ov5645->io_regulator for NULL.

and the error handling will be simply

if (IS_ERR(ret_reg))
	return PTR_ERR(ret_reg);

<cut>

> +
> +	ov5645->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW);
> +	if (IS_ERR(ov5645->pwdn_gpio)) {
> +		switch(PTR_ERR(ov5645->pwdn_gpio)) {
> +		case -ENOENT:
> +			/* GPIO is optional so this is ok - continue */

you can use devm_gpiod_get_optional then.

> +			ov5645->pwdn_gpio = NULL;
> +			dev_dbg(dev, "power down gpio not present\n");
> +			break;
> +		case -EPROBE_DEFER:
> +			dev_dbg(dev, "power down gpio probe defered\n");
> +			return -EPROBE_DEFER;
> +		default:
> +			dev_err(dev, "cannot get power down gpio\n");
> +			return PTR_ERR(ov5645->pwdn_gpio);
> +		}
> +	}


-- 
regards,
Stan

  reply	other threads:[~2016-05-20 15:20 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-18 11:50 [PATCH v2 0/2] OV5645 camera sensor driver Todor Tomov
     [not found] ` <1463572208-8826-1-git-send-email-todor.tomov-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2016-05-18 11:50   ` [PATCH v2 1/2] [media] media: i2c/ov5645: add the device tree binding document Todor Tomov
2016-05-18 11:50     ` Todor Tomov
2016-05-18 23:16     ` Rob Herring
2016-05-19  8:14       ` Todor Tomov
2016-05-20  0:16         ` Rob Herring
2016-05-20  8:20           ` Todor Tomov
2016-05-18 11:50 ` [PATCH v2 2/2] media: Add a driver for the ov5645 camera sensor Todor Tomov
2016-05-20 15:20   ` Stanimir Varbanov [this message]
2016-05-27 11:59     ` Todor Tomov
2016-05-23 10:36   ` Hans Verkuil
     [not found]     ` <5742DD2A.3010706-qWit8jRvyhVmR6Xm/wNWPw@public.gmane.org>
2016-05-26  8:55       ` Todor Tomov
2016-05-26  8:55         ` Todor Tomov

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=573F2B31.1070807@linaro.org \
    --to=stanimir.varbanov@linaro.org \
    --cc=devicetree@vger.kernel.org \
    --cc=galak@codeaurora.org \
    --cc=geert@linux-m68k.org \
    --cc=hverkuil@xs4all.nl \
    --cc=ijc+devicetree@hellion.org.uk \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linux-media@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=matrandg@cisco.com \
    --cc=mchehab@osg.samsung.com \
    --cc=pawel.moll@arm.com \
    --cc=robh+dt@kernel.org \
    --cc=todor.tomov@linaro.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.