diff options
author | Jonathan Corbet <corbet@lwn.net> | 2010-02-28 19:02:55 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-05-17 23:51:21 -0400 |
commit | 2bf7de48888fceed8d8e5cddd51f1d474bdbfae6 (patch) | |
tree | a78e5ea63fb06bd19fa8735dfe216b47f7aeb7f4 /drivers/media/video/ov7670.c | |
parent | d8d201552f518370d0a64cb758684f667fdd2012 (diff) |
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/media/video/ov7670.c')
-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 b2e6f8e730a3..95507770f120 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c | |||
@@ -410,16 +410,33 @@ static struct regval_list ov7670_fmt_raw[] = { | |||
410 | /* | 410 | /* |
411 | * Low-level register I/O. | 411 | * Low-level register I/O. |
412 | */ | 412 | */ |
413 | |||
414 | static int ov7670_read(struct v4l2_subdev *sd, unsigned char reg, | 413 | static int ov7670_read(struct v4l2_subdev *sd, unsigned char reg, |
415 | unsigned char *value) | 414 | unsigned char *value) |
416 | { | 415 | { |
417 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 416 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
417 | u8 data = reg; | ||
418 | struct i2c_msg msg; | ||
418 | int ret; | 419 | int ret; |
419 | 420 | ||
420 | ret = i2c_smbus_read_byte_data(client, reg); | 421 | /* |
422 | * Send out the register address... | ||
423 | */ | ||
424 | msg.addr = client->addr; | ||
425 | msg.flags = 0; | ||
426 | msg.len = 1; | ||
427 | msg.buf = &data; | ||
428 | ret = i2c_transfer(client->adapter, &msg, 1); | ||
429 | if (ret < 0) { | ||
430 | printk(KERN_ERR "Error %d on register write\n", ret); | ||
431 | return ret; | ||
432 | } | ||
433 | /* | ||
434 | * ...then read back the result. | ||
435 | */ | ||
436 | msg.flags = I2C_M_RD; | ||
437 | ret = i2c_transfer(client->adapter, &msg, 1); | ||
421 | if (ret >= 0) { | 438 | if (ret >= 0) { |
422 | *value = (unsigned char)ret; | 439 | *value = data; |
423 | ret = 0; | 440 | ret = 0; |
424 | } | 441 | } |
425 | return ret; | 442 | return ret; |
@@ -430,8 +447,17 @@ static int ov7670_write(struct v4l2_subdev *sd, unsigned char reg, | |||
430 | unsigned char value) | 447 | unsigned char value) |
431 | { | 448 | { |
432 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 449 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
433 | int ret = i2c_smbus_write_byte_data(client, reg, value); | 450 | struct i2c_msg msg; |
451 | unsigned char data[2] = { reg, value }; | ||
452 | int ret; | ||
434 | 453 | ||
454 | msg.addr = client->addr; | ||
455 | msg.flags = 0; | ||
456 | msg.len = 2; | ||
457 | msg.buf = data; | ||
458 | ret = i2c_transfer(client->adapter, &msg, 1); | ||
459 | if (ret > 0) | ||
460 | ret = 0; | ||
435 | if (reg == REG_COM7 && (value & COM7_RESET)) | 461 | if (reg == REG_COM7 && (value & COM7_RESET)) |
436 | msleep(5); /* Wait for reset to run */ | 462 | msleep(5); /* Wait for reset to run */ |
437 | return ret; | 463 | return ret; |