2020-08-03 11:46:07

by Prabhakar Mahadev Lad

[permalink] [raw]
Subject: [PATCH v2 0/3] media: i2c: ov772x: Enable BT656 mode and test pattern support

Hi All,

This patch series adds support for BT656 mode in the ov772x sensor
and also enables color bar test pattern control.

Cheers,
Prabhakar

Changes for v2:
* Updated DT bindings
* Driver defaults to parallel mode
* Fixed return type when endpoint parsing fails

Lad Prabhakar (3):
dt-bindings: media: ov772x: Document endpoint properties
media: i2c: ov772x: Add support for BT656 mode
media: i2c: ov772x: Add test pattern control

.../devicetree/bindings/media/i2c/ov772x.txt | 16 +++++
drivers/media/i2c/ov772x.c | 65 ++++++++++++++++++-
include/media/i2c/ov772x.h | 1 +
3 files changed, 81 insertions(+), 1 deletion(-)

--
2.17.1


2020-08-03 11:47:04

by Prabhakar Mahadev Lad

[permalink] [raw]
Subject: [PATCH v2 2/3] media: i2c: ov772x: Add support for BT656 mode

Add support to read the bus-type and enable BT656 mode if needed.

The driver defaults to parallel mode if bus-type is not specified in DT.

Signed-off-by: Lad Prabhakar <[email protected]>
Reviewed-by: Biju Das <[email protected]>
---
drivers/media/i2c/ov772x.c | 40 ++++++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)

diff --git a/drivers/media/i2c/ov772x.c b/drivers/media/i2c/ov772x.c
index 2cc6a678069a..2de9248e3689 100644
--- a/drivers/media/i2c/ov772x.c
+++ b/drivers/media/i2c/ov772x.c
@@ -31,6 +31,7 @@
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-event.h>
+#include <media/v4l2-fwnode.h>
#include <media/v4l2-image-sizes.h>
#include <media/v4l2-subdev.h>

@@ -434,6 +435,7 @@ struct ov772x_priv {
#ifdef CONFIG_MEDIA_CONTROLLER
struct media_pad pad;
#endif
+ struct v4l2_fwnode_endpoint ep;
};

/*
@@ -574,6 +576,7 @@ static int ov772x_s_stream(struct v4l2_subdev *sd, int enable)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov772x_priv *priv = to_ov772x(sd);
+ unsigned int val;
int ret = 0;

mutex_lock(&priv->lock);
@@ -581,6 +584,22 @@ static int ov772x_s_stream(struct v4l2_subdev *sd, int enable)
if (priv->streaming == enable)
goto done;

+ if (priv->ep.bus_type == V4L2_MBUS_BT656 && enable) {
+ ret = regmap_read(priv->regmap, COM7, &val);
+ if (ret)
+ goto done;
+ val |= ITU656_ON_OFF;
+ ret = regmap_write(priv->regmap, COM7, val);
+ } else if (priv->ep.bus_type == V4L2_MBUS_BT656 && !enable) {
+ ret = regmap_read(priv->regmap, COM7, &val);
+ if (ret)
+ goto done;
+ val &= ~ITU656_ON_OFF;
+ ret = regmap_write(priv->regmap, COM7, val);
+ }
+ if (ret)
+ goto done;
+
ret = regmap_update_bits(priv->regmap, COM2, SOFT_SLEEP_MODE,
enable ? 0 : SOFT_SLEEP_MODE);
if (ret)
@@ -1354,6 +1373,7 @@ static const struct v4l2_subdev_ops ov772x_subdev_ops = {

static int ov772x_probe(struct i2c_client *client)
{
+ struct fwnode_handle *endpoint;
struct ov772x_priv *priv;
int ret;
static const struct regmap_config ov772x_regmap_config = {
@@ -1415,6 +1435,26 @@ static int ov772x_probe(struct i2c_client *client)
goto error_clk_put;
}

+ endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev),
+ NULL);
+ if (!endpoint) {
+ dev_err(&client->dev, "endpoint node not found\n");
+ ret = -EINVAL;
+ goto error_clk_put;
+ }
+
+ ret = v4l2_fwnode_endpoint_parse(endpoint, &priv->ep);
+ fwnode_handle_put(endpoint);
+ if (ret) {
+ dev_err(&client->dev, "Could not parse endpoint\n");
+ goto error_clk_put;
+ }
+
+ /* fallback to parallel mode */
+ if (priv->ep.bus_type != V4L2_MBUS_PARALLEL &&
+ priv->ep.bus_type != V4L2_MBUS_BT656)
+ priv->ep.bus_type = V4L2_MBUS_PARALLEL;
+
ret = ov772x_video_probe(priv);
if (ret < 0)
goto error_gpio_put;
--
2.17.1

2020-08-03 11:51:25

by Prabhakar Mahadev Lad

[permalink] [raw]
Subject: [PATCH v2 3/3] media: i2c: ov772x: Add test pattern control

Add support for test pattern control supported by the sensor.

Signed-off-by: Lad Prabhakar <[email protected]>
Reviewed-by: Biju Das <[email protected]>
---
drivers/media/i2c/ov772x.c | 25 ++++++++++++++++++++++++-
include/media/i2c/ov772x.h | 1 +
2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/media/i2c/ov772x.c b/drivers/media/i2c/ov772x.c
index 2de9248e3689..457887ec548d 100644
--- a/drivers/media/i2c/ov772x.c
+++ b/drivers/media/i2c/ov772x.c
@@ -227,7 +227,7 @@

/* COM3 */
#define SWAP_MASK (SWAP_RGB | SWAP_YUV | SWAP_ML)
-#define IMG_MASK (VFLIP_IMG | HFLIP_IMG)
+#define IMG_MASK (VFLIP_IMG | HFLIP_IMG | SCOLOR_TEST)

#define VFLIP_IMG 0x80 /* Vertical flip image ON/OFF selection */
#define HFLIP_IMG 0x40 /* Horizontal mirror image ON/OFF selection */
@@ -425,6 +425,7 @@ struct ov772x_priv {
const struct ov772x_win_size *win;
struct v4l2_ctrl *vflip_ctrl;
struct v4l2_ctrl *hflip_ctrl;
+ unsigned int test_pattern;
/* band_filter = COM8[5] ? 256 - BDBASE : 0 */
struct v4l2_ctrl *band_filter_ctrl;
unsigned int fps;
@@ -540,6 +541,11 @@ static const struct ov772x_win_size ov772x_win_sizes[] = {
},
};

+static const char * const ov772x_test_pattern_menu[] = {
+ "Disabled",
+ "Vertical Color Bar Type 1",
+};
+
/*
* frame rate settings lists
*/
@@ -772,6 +778,13 @@ static int ov772x_s_frame_interval(struct v4l2_subdev *sd,
return ret;
}

+static int ov772x_enable_test_pattern(struct ov772x_priv *priv, u32 pattern)
+{
+ priv->test_pattern = pattern;
+ return regmap_update_bits(priv->regmap, COM3, SCOLOR_TEST,
+ pattern ? SCOLOR_TEST : 0x00);
+}
+
static int ov772x_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct ov772x_priv *priv = container_of(ctrl->handler,
@@ -819,6 +832,8 @@ static int ov772x_s_ctrl(struct v4l2_ctrl *ctrl)
}

return ret;
+ case V4L2_CID_TEST_PATTERN:
+ return ov772x_enable_test_pattern(priv, ctrl->val);
}

return -EINVAL;
@@ -1113,10 +1128,14 @@ static int ov772x_set_params(struct ov772x_priv *priv,
val |= VFLIP_IMG;
if (priv->info && (priv->info->flags & OV772X_FLAG_HFLIP))
val |= HFLIP_IMG;
+ if (priv->info && (priv->info->flags & OV772X_FLAG_TEST_PATTERN))
+ val |= SCOLOR_TEST;
if (priv->vflip_ctrl->val)
val ^= VFLIP_IMG;
if (priv->hflip_ctrl->val)
val ^= HFLIP_IMG;
+ if (priv->test_pattern)
+ val ^= SCOLOR_TEST;

ret = regmap_update_bits(priv->regmap, COM3, SWAP_MASK | IMG_MASK, val);
if (ret < 0)
@@ -1414,6 +1433,10 @@ static int ov772x_probe(struct i2c_client *client)
priv->band_filter_ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops,
V4L2_CID_BAND_STOP_FILTER,
0, 256, 1, 0);
+ v4l2_ctrl_new_std_menu_items(&priv->hdl, &ov772x_ctrl_ops,
+ V4L2_CID_TEST_PATTERN,
+ ARRAY_SIZE(ov772x_test_pattern_menu) - 1,
+ 0, 0, ov772x_test_pattern_menu);
priv->subdev.ctrl_handler = &priv->hdl;
if (priv->hdl.error) {
ret = priv->hdl.error;
diff --git a/include/media/i2c/ov772x.h b/include/media/i2c/ov772x.h
index a1702d420087..65e6f8d2f4bb 100644
--- a/include/media/i2c/ov772x.h
+++ b/include/media/i2c/ov772x.h
@@ -12,6 +12,7 @@
/* for flags */
#define OV772X_FLAG_VFLIP (1 << 0) /* Vertical flip image */
#define OV772X_FLAG_HFLIP (1 << 1) /* Horizontal flip image */
+#define OV772X_FLAG_TEST_PATTERN (1 << 2) /* Test pattern */

/*
* for Edge ctrl
--
2.17.1

2020-08-06 17:15:27

by jacopo mondi

[permalink] [raw]
Subject: Re: [PATCH v2 2/3] media: i2c: ov772x: Add support for BT656 mode

On Mon, Aug 03, 2020 at 12:39:12PM +0100, Lad Prabhakar wrote:
> Add support to read the bus-type and enable BT656 mode if needed.
>
> The driver defaults to parallel mode if bus-type is not specified in DT.
>
> Signed-off-by: Lad Prabhakar <[email protected]>
> Reviewed-by: Biju Das <[email protected]>
> ---
> drivers/media/i2c/ov772x.c | 40 ++++++++++++++++++++++++++++++++++++++
> 1 file changed, 40 insertions(+)
>
> diff --git a/drivers/media/i2c/ov772x.c b/drivers/media/i2c/ov772x.c
> index 2cc6a678069a..2de9248e3689 100644
> --- a/drivers/media/i2c/ov772x.c
> +++ b/drivers/media/i2c/ov772x.c
> @@ -31,6 +31,7 @@
> #include <media/v4l2-ctrls.h>
> #include <media/v4l2-device.h>
> #include <media/v4l2-event.h>
> +#include <media/v4l2-fwnode.h>
> #include <media/v4l2-image-sizes.h>
> #include <media/v4l2-subdev.h>
>
> @@ -434,6 +435,7 @@ struct ov772x_priv {
> #ifdef CONFIG_MEDIA_CONTROLLER
> struct media_pad pad;
> #endif
> + struct v4l2_fwnode_endpoint ep;
> };
>
> /*
> @@ -574,6 +576,7 @@ static int ov772x_s_stream(struct v4l2_subdev *sd, int enable)
> {
> struct i2c_client *client = v4l2_get_subdevdata(sd);
> struct ov772x_priv *priv = to_ov772x(sd);
> + unsigned int val;
> int ret = 0;
>
> mutex_lock(&priv->lock);
> @@ -581,6 +584,22 @@ static int ov772x_s_stream(struct v4l2_subdev *sd, int enable)
> if (priv->streaming == enable)
> goto done;
>
> + if (priv->ep.bus_type == V4L2_MBUS_BT656 && enable) {
> + ret = regmap_read(priv->regmap, COM7, &val);
> + if (ret)
> + goto done;
> + val |= ITU656_ON_OFF;
> + ret = regmap_write(priv->regmap, COM7, val);
> + } else if (priv->ep.bus_type == V4L2_MBUS_BT656 && !enable) {

is the !enable intentional ? (sorry I don't have access to the sensor
manual). If not, see below:

> + ret = regmap_read(priv->regmap, COM7, &val);
> + if (ret)
> + goto done;
> + val &= ~ITU656_ON_OFF;
> + ret = regmap_write(priv->regmap, COM7, val);
> + }
> + if (ret)
> + goto done;

Could you write this as:

static int ov772x_s_stream(struct v4l2_subdev *sd, int enable)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov772x_priv *priv = to_ov772x(sd);
int ret = 0;

mutex_lock(&priv->lock);

if (priv->streaming == enable)
goto done;

if (enable) {
ret = regmap_read(priv->regmap, COM7, &val);
if (ret)
goto done;

if (priv->ep.bus_type == V4L2_MBUS_BT656)
val |= ITU656_ON_OFF;
else /* if you accept my suggestion to consider othe
bus types as errors */
val &= ~ITU656_ON_OFF;

ret = regmap_write(priv->regmap, COM7, val);
if (ret)
goto done;

dev_dbg(&client->dev, "format %d, win %s\n",
priv->cfmt->code, priv->win->name);
}

ret = regmap_update_bits(priv->regmap, COM2, SOFT_SLEEP_MODE,
enable ? 0 : SOFT_SLEEP_MODE);
if (ret)
goto done;
priv->streaming = enable;

done:
mutex_unlock(&priv->lock);

return ret;
}


> ret = regmap_update_bits(priv->regmap, COM2, SOFT_SLEEP_MODE,
> enable ? 0 : SOFT_SLEEP_MODE);
> if (ret)
> @@ -1354,6 +1373,7 @@ static const struct v4l2_subdev_ops ov772x_subdev_ops = {
>
> static int ov772x_probe(struct i2c_client *client)
> {
> + struct fwnode_handle *endpoint;
> struct ov772x_priv *priv;
> int ret;
> static const struct regmap_config ov772x_regmap_config = {
> @@ -1415,6 +1435,26 @@ static int ov772x_probe(struct i2c_client *client)
> goto error_clk_put;
> }
>
> + endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev),
> + NULL);
> + if (!endpoint) {
> + dev_err(&client->dev, "endpoint node not found\n");
> + ret = -EINVAL;
> + goto error_clk_put;
> + }
> +
> + ret = v4l2_fwnode_endpoint_parse(endpoint, &priv->ep);
> + fwnode_handle_put(endpoint);
> + if (ret) {
> + dev_err(&client->dev, "Could not parse endpoint\n");
> + goto error_clk_put;
> + }
> +
> + /* fallback to parallel mode */
> + if (priv->ep.bus_type != V4L2_MBUS_PARALLEL &&
> + priv->ep.bus_type != V4L2_MBUS_BT656)
> + priv->ep.bus_type = V4L2_MBUS_PARALLEL;

shouldn't this be an error ? It's either the bus type has not been
specified on DT (which is fine, otherwise old DTB without that
properties will fail) and the bus identification routine implemented
in v4l2_fwnode_endpoint_parse() detected a bus type which is not
supported, hence the DT properties are wrong, and this should be an
error. If you plan to expand the parsing routine to support, say
bus-width and pclk polarity please break this out to a new function.

Thanks
j

> +
> ret = ov772x_video_probe(priv);
> if (ret < 0)
> goto error_gpio_put;
> --
> 2.17.1
>

2020-08-10 07:29:21

by Lad, Prabhakar

[permalink] [raw]
Subject: Re: [PATCH v2 2/3] media: i2c: ov772x: Add support for BT656 mode

Hi Jacopo,

Thank you for the review.

On Thu, Aug 6, 2020 at 3:41 PM Jacopo Mondi <[email protected]> wrote:
>
> On Mon, Aug 03, 2020 at 12:39:12PM +0100, Lad Prabhakar wrote:
> > Add support to read the bus-type and enable BT656 mode if needed.
> >
> > The driver defaults to parallel mode if bus-type is not specified in DT.
> >
> > Signed-off-by: Lad Prabhakar <[email protected]>
> > Reviewed-by: Biju Das <[email protected]>
> > ---
> > drivers/media/i2c/ov772x.c | 40 ++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 40 insertions(+)
> >
> > diff --git a/drivers/media/i2c/ov772x.c b/drivers/media/i2c/ov772x.c
> > index 2cc6a678069a..2de9248e3689 100644
> > --- a/drivers/media/i2c/ov772x.c
> > +++ b/drivers/media/i2c/ov772x.c
> > @@ -31,6 +31,7 @@
> > #include <media/v4l2-ctrls.h>
> > #include <media/v4l2-device.h>
> > #include <media/v4l2-event.h>
> > +#include <media/v4l2-fwnode.h>
> > #include <media/v4l2-image-sizes.h>
> > #include <media/v4l2-subdev.h>
> >
> > @@ -434,6 +435,7 @@ struct ov772x_priv {
> > #ifdef CONFIG_MEDIA_CONTROLLER
> > struct media_pad pad;
> > #endif
> > + struct v4l2_fwnode_endpoint ep;
> > };
> >
> > /*
> > @@ -574,6 +576,7 @@ static int ov772x_s_stream(struct v4l2_subdev *sd, int enable)
> > {
> > struct i2c_client *client = v4l2_get_subdevdata(sd);
> > struct ov772x_priv *priv = to_ov772x(sd);
> > + unsigned int val;
> > int ret = 0;
> >
> > mutex_lock(&priv->lock);
> > @@ -581,6 +584,22 @@ static int ov772x_s_stream(struct v4l2_subdev *sd, int enable)
> > if (priv->streaming == enable)
> > goto done;
> >
> > + if (priv->ep.bus_type == V4L2_MBUS_BT656 && enable) {
> > + ret = regmap_read(priv->regmap, COM7, &val);
> > + if (ret)
> > + goto done;
> > + val |= ITU656_ON_OFF;
> > + ret = regmap_write(priv->regmap, COM7, val);
> > + } else if (priv->ep.bus_type == V4L2_MBUS_BT656 && !enable) {
>
> is the !enable intentional ? (sorry I don't have access to the sensor
> manual). If not, see below:
>
> > + ret = regmap_read(priv->regmap, COM7, &val);
> > + if (ret)
> > + goto done;
> > + val &= ~ITU656_ON_OFF;
> > + ret = regmap_write(priv->regmap, COM7, val);
> > + }
> > + if (ret)
> > + goto done;
>
> Could you write this as:
>
Agreed will do.

> static int ov772x_s_stream(struct v4l2_subdev *sd, int enable)
> {
> struct i2c_client *client = v4l2_get_subdevdata(sd);
> struct ov772x_priv *priv = to_ov772x(sd);
> int ret = 0;
>
> mutex_lock(&priv->lock);
>
> if (priv->streaming == enable)
> goto done;
>
> if (enable) {
> ret = regmap_read(priv->regmap, COM7, &val);
> if (ret)
> goto done;
>
> if (priv->ep.bus_type == V4L2_MBUS_BT656)
> val |= ITU656_ON_OFF;
> else /* if you accept my suggestion to consider othe
> bus types as errors */
> val &= ~ITU656_ON_OFF;
>
> ret = regmap_write(priv->regmap, COM7, val);
> if (ret)
> goto done;
>
> dev_dbg(&client->dev, "format %d, win %s\n",
> priv->cfmt->code, priv->win->name);
> }
>
> ret = regmap_update_bits(priv->regmap, COM2, SOFT_SLEEP_MODE,
> enable ? 0 : SOFT_SLEEP_MODE);
> if (ret)
> goto done;
> priv->streaming = enable;
>
> done:
> mutex_unlock(&priv->lock);
>
> return ret;
> }
>
>
> > ret = regmap_update_bits(priv->regmap, COM2, SOFT_SLEEP_MODE,
> > enable ? 0 : SOFT_SLEEP_MODE);
> > if (ret)
> > @@ -1354,6 +1373,7 @@ static const struct v4l2_subdev_ops ov772x_subdev_ops = {
> >
> > static int ov772x_probe(struct i2c_client *client)
> > {
> > + struct fwnode_handle *endpoint;
> > struct ov772x_priv *priv;
> > int ret;
> > static const struct regmap_config ov772x_regmap_config = {
> > @@ -1415,6 +1435,26 @@ static int ov772x_probe(struct i2c_client *client)
> > goto error_clk_put;
> > }
> >
> > + endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev),
> > + NULL);
> > + if (!endpoint) {
> > + dev_err(&client->dev, "endpoint node not found\n");
> > + ret = -EINVAL;
> > + goto error_clk_put;
> > + }
> > +
> > + ret = v4l2_fwnode_endpoint_parse(endpoint, &priv->ep);
> > + fwnode_handle_put(endpoint);
> > + if (ret) {
> > + dev_err(&client->dev, "Could not parse endpoint\n");
> > + goto error_clk_put;
> > + }
> > +
> > + /* fallback to parallel mode */
> > + if (priv->ep.bus_type != V4L2_MBUS_PARALLEL &&
> > + priv->ep.bus_type != V4L2_MBUS_BT656)
> > + priv->ep.bus_type = V4L2_MBUS_PARALLEL;
>
> shouldn't this be an error ? It's either the bus type has not been
> specified on DT (which is fine, otherwise old DTB without that
> properties will fail) and the bus identification routine implemented
> in v4l2_fwnode_endpoint_parse() detected a bus type which is not
> supported, hence the DT properties are wrong, and this should be an
> error. If you plan to expand the parsing routine to support, say
> bus-width and pclk polarity please break this out to a new function.
>
Agreed.

Cheers,
Prabhakar

> Thanks
> j
>
> > +
> > ret = ov772x_video_probe(priv);
> > if (ret < 0)
> > goto error_gpio_put;
> > --
> > 2.17.1
> >