diff options
author | Jonathan Corbet <corbet@lwn.net> | 2010-03-01 00:02:55 (GMT) |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-05-18 03:51:21 (GMT) |
commit | 2bf7de48888fceed8d8e5cddd51f1d474bdbfae6 (patch) | |
tree | a78e5ea63fb06bd19fa8735dfe216b47f7aeb7f4 /drivers | |
parent | d8d201552f518370d0a64cb758684f667fdd2012 (diff) | |
download | linux-2bf7de48888fceed8d8e5cddd51f1d474bdbfae6.tar.xz |
V4L/DVB: ov7670: Don't use SMBUS I/O
Contrary to my earlier belief, the ov7670 is not actually an SMBUS device,
though it will pretend to be one if it's in a good mood. Unfortunately,
it's rarely in a good mood, especially on the XO 1.5. So use low-level i2c
I/O instead.
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/ov7670.c | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index b2e6f8e..95507770 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c @@ -410,16 +410,33 @@ static struct regval_list ov7670_fmt_raw[] = { /* * Low-level register I/O. */ - static int ov7670_read(struct v4l2_subdev *sd, unsigned char reg, unsigned char *value) { struct i2c_client *client = v4l2_get_subdevdata(sd); + u8 data = reg; + struct i2c_msg msg; int ret; - ret = i2c_smbus_read_byte_data(client, reg); + /* + * Send out the register address... + */ + msg.addr = client->addr; + msg.flags = 0; + msg.len = 1; + msg.buf = &data; + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret < 0) { + printk(KERN_ERR "Error %d on register write\n", ret); + return ret; + } + /* + * ...then read back the result. + */ + msg.flags = I2C_M_RD; + ret = i2c_transfer(client->adapter, &msg, 1); if (ret >= 0) { - *value = (unsigned char)ret; + *value = data; ret = 0; } return ret; @@ -430,8 +447,17 @@ static int ov7670_write(struct v4l2_subdev *sd, unsigned char reg, unsigned char value) { struct i2c_client *client = v4l2_get_subdevdata(sd); - int ret = i2c_smbus_write_byte_data(client, reg, value); + struct i2c_msg msg; + unsigned char data[2] = { reg, value }; + int ret; + msg.addr = client->addr; + msg.flags = 0; + msg.len = 2; + msg.buf = data; + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret > 0) + ret = 0; if (reg == REG_COM7 && (value & COM7_RESET)) msleep(5); /* Wait for reset to run */ return ret; |