diff options
author | Jacopo Mondi <jacopo.mondi@ideasonboard.com> | 2023-02-21 20:10:48 +0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@kernel.org> | 2023-03-20 10:55:57 +0300 |
commit | 0d840d425e77c85606488bb6869d72a57fcbd04b (patch) | |
tree | 8ceb564912b44cde60c07235d7200ebddea4b8f8 | |
parent | ca4331bd0d6d8590d999d2cef93f0bfe9266bb21 (diff) | |
download | linux-0d840d425e77c85606488bb6869d72a57fcbd04b.tar.xz |
media: i2c: ov5647: Use bus-locked i2c_transfer()
The ov5647_read() functions calls i2c_master_send() and
i2c_master_read() in sequence. However this leaves space for other
clients to contend the bus and insert an unrelated transaction in between
the two calls.
Replace the two calls with a single i2c_transfer() one, that locks the
bus in between the transactions.
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Tommaso Merciai <tomm.merciai@gmail.com>
Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
-rw-r--r-- | drivers/media/i2c/ov5647.c | 30 |
1 files changed, 18 insertions, 12 deletions
diff --git a/drivers/media/i2c/ov5647.c b/drivers/media/i2c/ov5647.c index 2a9024ce2682..233576ee9503 100644 --- a/drivers/media/i2c/ov5647.c +++ b/drivers/media/i2c/ov5647.c @@ -629,23 +629,29 @@ static int ov5647_write(struct v4l2_subdev *sd, u16 reg, u8 val) static int ov5647_read(struct v4l2_subdev *sd, u16 reg, u8 *val) { - unsigned char data_w[2] = { reg >> 8, reg & 0xff }; struct i2c_client *client = v4l2_get_subdevdata(sd); + u8 buf[2] = { reg >> 8, reg & 0xff }; + struct i2c_msg msg[2]; int ret; - ret = i2c_master_send(client, data_w, 2); - if (ret < 0) { - dev_dbg(&client->dev, "%s: i2c write error, reg: %x\n", - __func__, reg); - return ret; + msg[0].addr = client->addr; + msg[0].flags = client->flags; + msg[0].buf = buf; + msg[0].len = sizeof(buf); + + msg[1].addr = client->addr; + msg[1].flags = client->flags | I2C_M_RD; + msg[1].buf = buf; + msg[1].len = 1; + + ret = i2c_transfer(client->adapter, msg, 2); + if (ret != 2) { + dev_err(&client->dev, "%s: i2c read error, reg: %x = %d\n", + __func__, reg, ret); + return ret >= 0 ? -EINVAL : ret; } - ret = i2c_master_recv(client, val, 1); - if (ret < 0) { - dev_dbg(&client->dev, "%s: i2c read error, reg: %x\n", - __func__, reg); - return ret; - } + *val = buf[0]; return 0; } |