summary refs log tree commit diff
path: root/drivers/i2c
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2009-09-18 22:45:44 +0200
committerJean Delvare <khali@linux-fr.org>2009-09-18 22:45:44 +0200
commitac7809414fb1e3e49b88ad6016e57598594aa4e2 (patch)
treeb00de5f5130f8b21bc1be49e5b90c0190aed555d /drivers/i2c
parent27693ce5f372c0af3b0730f5152b35432afa0fd7 (diff)
downloadlinux-ac7809414fb1e3e49b88ad6016e57598594aa4e2.tar.gz
i2c/tsl2550: Use combined SMBus transactions
Make the I/O faster, mainly by using combined SMBus transactions when
possible. While the TSL2550 datasheet doesn't say the device supports
them, they seem to work just fine in practice, and a combined
transaction is faster than two simple transactions in many cases and
always more reliable.

A side effect is to suppress the delays between SMBus writes and
reads. The datasheet doesn't say they are needed and things work just
fine for me without them.

I also couldn't see any reason for the delay between reading the two
channels. Nor for the loop to get a reading in the first place. The
400 ms delay between samples only matters at chip power-up, after that
the chip always hold the previously sampled value so we never get to
wait.

All these changes make reading the lux value much faster and cheaper.

Signed-off-by: Jean Delvare <khali@linux-fr.org>
Tested-by: Michele De Candia <michele.decandia@valueteam.com>
Cc: Rodolfo Giometti <giometti@linux.it>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/chips/tsl2550.c42
1 files changed, 10 insertions, 32 deletions
diff --git a/drivers/i2c/chips/tsl2550.c b/drivers/i2c/chips/tsl2550.c
index b96f3025e588..aa96bd2d27ea 100644
--- a/drivers/i2c/chips/tsl2550.c
+++ b/drivers/i2c/chips/tsl2550.c
@@ -24,10 +24,9 @@
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/mutex.h>
-#include <linux/delay.h>
 
 #define TSL2550_DRV_NAME	"tsl2550"
-#define DRIVER_VERSION		"1.1.2"
+#define DRIVER_VERSION		"1.2"
 
 /*
  * Defines
@@ -96,32 +95,13 @@ static int tsl2550_set_power_state(struct i2c_client *client, int state)
 
 static int tsl2550_get_adc_value(struct i2c_client *client, u8 cmd)
 {
-	unsigned long end;
-	int loop = 0, ret = 0;
+	int ret;
 
-	/*
-	 * Read ADC channel waiting at most 400ms (see data sheet for further
-	 * info).
-	 * To avoid long busy wait we spin for few milliseconds then
-	 * start sleeping.
-	 */
-	end = jiffies + msecs_to_jiffies(400);
-	while (time_before(jiffies, end)) {
-		i2c_smbus_write_byte(client, cmd);
-
-		if (loop++ < 5)
-			mdelay(1);
-		else
-			msleep(1);
-
-		ret = i2c_smbus_read_byte(client);
-		if (ret < 0)
-			return ret;
-		else if (ret & 0x0080)
-			break;
-	}
+	ret = i2c_smbus_read_byte_data(client, cmd);
+	if (ret < 0)
+		return ret;
 	if (!(ret & 0x80))
-		return -EIO;
+		return -EAGAIN;
 	return ret & 0x7f;	/* remove the "valid" bit */
 }
 
@@ -285,8 +265,6 @@ static ssize_t __tsl2550_show_lux(struct i2c_client *client, char *buf)
 		return ret;
 	ch0 = ret;
 
-	mdelay(1);
-
 	ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC1);
 	if (ret < 0)
 		return ret;
@@ -345,11 +323,10 @@ static int tsl2550_init_client(struct i2c_client *client)
 	 * Probe the chip. To do so we try to power up the device and then to
 	 * read back the 0x03 code
 	 */
-	err = i2c_smbus_write_byte(client, TSL2550_POWER_UP);
+	err = i2c_smbus_read_byte_data(client, TSL2550_POWER_UP);
 	if (err < 0)
 		return err;
-	mdelay(1);
-	if (i2c_smbus_read_byte(client) != TSL2550_POWER_UP)
+	if (err != TSL2550_POWER_UP)
 		return -ENODEV;
 	data->power_state = 1;
 
@@ -374,7 +351,8 @@ static int __devinit tsl2550_probe(struct i2c_client *client,
 	struct tsl2550_data *data;
 	int *opmode, err = 0;
 
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) {
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE
+					    | I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
 		err = -EIO;
 		goto exit;
 	}