Skip to content

Commit 037e688

Browse files
Jacopo Mondiehristev
authored andcommitted
media: v4l2: i2c: ov7670: Implement OF mbus configuration
ov7670 driver supports two optional properties supplied through platform data, but currently does not support any standard video interface property. Add support through OF parsing for 2 generic properties (vsync and hsync polarities) and for one custom property already supported through platform data to suppress pixel clock output during horizontal blanking. While at there, check return value of register writes in set_fmt function and rationalize spacings. Signal polarities and pixel clock blanking verified through scope and image capture. Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
1 parent 2220f29 commit 037e688

2 files changed

Lines changed: 85 additions & 14 deletions

File tree

drivers/media/i2c/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,7 @@ config VIDEO_OV7670
644644
tristate "OmniVision OV7670 sensor support"
645645
depends on I2C && VIDEO_V4L2
646646
depends on MEDIA_CAMERA_SUPPORT
647+
select V4L2_FWNODE
647648
---help---
648649
This is a Video4Linux2 sensor-level driver for the OmniVision
649650
OV7670 VGA camera. It currently only works with the M88ALP01

drivers/media/i2c/ov7670.c

Lines changed: 84 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <linux/gpio/consumer.h>
2222
#include <media/v4l2-device.h>
2323
#include <media/v4l2-ctrls.h>
24+
#include <media/v4l2-fwnode.h>
2425
#include <media/v4l2-mediabus.h>
2526
#include <media/v4l2-image-sizes.h>
2627
#include <media/i2c/ov7670.h>
@@ -242,6 +243,7 @@ struct ov7670_info {
242243
struct clk *clk;
243244
struct gpio_desc *resetb_gpio;
244245
struct gpio_desc *pwdn_gpio;
246+
unsigned int mbus_config; /* Media bus configuration flags */
245247
int min_width; /* Filter out smaller sizes */
246248
int min_height; /* Filter out smaller sizes */
247249
int clock_speed; /* External clock speed (MHz) */
@@ -1014,7 +1016,7 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd,
10141016
#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
10151017
struct v4l2_mbus_framefmt *mbus_fmt;
10161018
#endif
1017-
unsigned char com7;
1019+
unsigned char com7, com10 = 0;
10181020
int ret;
10191021

10201022
if (format->pad)
@@ -1034,7 +1036,6 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd,
10341036
}
10351037

10361038
ret = ov7670_try_fmt_internal(sd, &format->format, &ovfmt, &wsize);
1037-
10381039
if (ret)
10391040
return ret;
10401041
/*
@@ -1045,16 +1046,41 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd,
10451046
*/
10461047
com7 = ovfmt->regs[0].value;
10471048
com7 |= wsize->com7_bit;
1048-
ov7670_write(sd, REG_COM7, com7);
1049+
ret = ov7670_write(sd, REG_COM7, com7);
1050+
if (ret)
1051+
return ret;
1052+
1053+
/*
1054+
* Configure the media bus through COM10 register
1055+
*/
1056+
if (info->mbus_config & V4L2_MBUS_VSYNC_ACTIVE_LOW)
1057+
com10 |= COM10_VS_NEG;
1058+
if (info->mbus_config & V4L2_MBUS_HSYNC_ACTIVE_LOW)
1059+
com10 |= COM10_HREF_REV;
1060+
if (info->pclk_hb_disable)
1061+
com10 |= COM10_PCLK_HB;
1062+
ret = ov7670_write(sd, REG_COM10, com10);
1063+
if (ret)
1064+
return ret;
1065+
10491066
/*
10501067
* Now write the rest of the array. Also store start/stops
10511068
*/
1052-
ov7670_write_array(sd, ovfmt->regs + 1);
1053-
ov7670_set_hw(sd, wsize->hstart, wsize->hstop, wsize->vstart,
1054-
wsize->vstop);
1055-
ret = 0;
1056-
if (wsize->regs)
1069+
ret = ov7670_write_array(sd, ovfmt->regs + 1);
1070+
if (ret)
1071+
return ret;
1072+
1073+
ret = ov7670_set_hw(sd, wsize->hstart, wsize->hstop, wsize->vstart,
1074+
wsize->vstop);
1075+
if (ret)
1076+
return ret;
1077+
1078+
if (wsize->regs) {
10571079
ret = ov7670_write_array(sd, wsize->regs);
1080+
if (ret)
1081+
return ret;
1082+
}
1083+
10581084
info->fmt = ovfmt;
10591085

10601086
/*
@@ -1067,8 +1093,10 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd,
10671093
* to write it unconditionally, and that will make the frame
10681094
* rate persistent too.
10691095
*/
1070-
if (ret == 0)
1071-
ret = ov7670_write(sd, REG_CLKRC, info->clkrc);
1096+
ret = ov7670_write(sd, REG_CLKRC, info->clkrc);
1097+
if (ret)
1098+
return ret;
1099+
10721100
return 0;
10731101
}
10741102

@@ -1698,6 +1726,45 @@ static int ov7670_init_gpio(struct i2c_client *client, struct ov7670_info *info)
16981726
return 0;
16991727
}
17001728

1729+
/*
1730+
* ov7670_parse_dt() - Parse device tree to collect mbus configuration
1731+
* properties
1732+
*/
1733+
static int ov7670_parse_dt(struct device *dev,
1734+
struct ov7670_info *info)
1735+
{
1736+
struct fwnode_handle *fwnode = dev_fwnode(dev);
1737+
struct v4l2_fwnode_endpoint bus_cfg;
1738+
struct fwnode_handle *ep;
1739+
int ret;
1740+
1741+
if (!fwnode)
1742+
return -EINVAL;
1743+
1744+
info->pclk_hb_disable = false;
1745+
if (fwnode_property_present(fwnode, "ov7670,pclk-hb-disable"))
1746+
info->pclk_hb_disable = true;
1747+
1748+
ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
1749+
if (!ep)
1750+
return -EINVAL;
1751+
1752+
ret = v4l2_fwnode_endpoint_parse(ep, &bus_cfg);
1753+
if (ret) {
1754+
fwnode_handle_put(ep);
1755+
return ret;
1756+
}
1757+
1758+
if (bus_cfg.bus_type != V4L2_MBUS_PARALLEL) {
1759+
dev_err(dev, "Unsupported media bus type\n");
1760+
fwnode_handle_put(ep);
1761+
return ret;
1762+
}
1763+
info->mbus_config = bus_cfg.bus.parallel.flags;
1764+
1765+
return 0;
1766+
}
1767+
17011768
static int ov7670_probe(struct i2c_client *client,
17021769
const struct i2c_device_id *id)
17031770
{
@@ -1718,7 +1785,13 @@ static int ov7670_probe(struct i2c_client *client,
17181785
#endif
17191786

17201787
info->clock_speed = 30; /* default: a guess */
1721-
if (client->dev.platform_data) {
1788+
1789+
if (dev_fwnode(&client->dev)) {
1790+
ret = ov7670_parse_dt(&client->dev, info);
1791+
if (ret)
1792+
return ret;
1793+
1794+
} else if (client->dev.platform_data) {
17221795
struct ov7670_config *config = client->dev.platform_data;
17231796

17241797
/*
@@ -1785,9 +1858,6 @@ static int ov7670_probe(struct i2c_client *client,
17851858
tpf.denominator = 30;
17861859
info->devtype->set_framerate(sd, &tpf);
17871860

1788-
if (info->pclk_hb_disable)
1789-
ov7670_write(sd, REG_COM10, COM10_PCLK_HB);
1790-
17911861
v4l2_ctrl_handler_init(&info->hdl, 10);
17921862
v4l2_ctrl_new_std(&info->hdl, &ov7670_ctrl_ops,
17931863
V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);

0 commit comments

Comments
 (0)