diff options
author | Jean Delvare <khali@linux-fr.org> | 2009-09-18 16:45:44 -0400 |
---|---|---|
committer | Jean Delvare <khali@linux-fr.org> | 2009-09-18 16:45:44 -0400 |
commit | ac7809414fb1e3e49b88ad6016e57598594aa4e2 (patch) | |
tree | b00de5f5130f8b21bc1be49e5b90c0190aed555d | |
parent | 27693ce5f372c0af3b0730f5152b35432afa0fd7 (diff) |
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>
-rw-r--r-- | drivers/i2c/chips/tsl2550.c | 42 |
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 @@ | |||
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
26 | #include <linux/mutex.h> | 26 | #include <linux/mutex.h> |
27 | #include <linux/delay.h> | ||
28 | 27 | ||
29 | #define TSL2550_DRV_NAME "tsl2550" | 28 | #define TSL2550_DRV_NAME "tsl2550" |
30 | #define DRIVER_VERSION "1.1.2" | 29 | #define DRIVER_VERSION "1.2" |
31 | 30 | ||
32 | /* | 31 | /* |
33 | * Defines | 32 | * Defines |
@@ -96,32 +95,13 @@ static int tsl2550_set_power_state(struct i2c_client *client, int state) | |||
96 | 95 | ||
97 | static int tsl2550_get_adc_value(struct i2c_client *client, u8 cmd) | 96 | static int tsl2550_get_adc_value(struct i2c_client *client, u8 cmd) |
98 | { | 97 | { |
99 | unsigned long end; | 98 | int ret; |
100 | int loop = 0, ret = 0; | ||
101 | 99 | ||
102 | /* | 100 | ret = i2c_smbus_read_byte_data(client, cmd); |
103 | * Read ADC channel waiting at most 400ms (see data sheet for further | 101 | if (ret < 0) |
104 | * info). | 102 | return ret; |
105 | * To avoid long busy wait we spin for few milliseconds then | ||
106 | * start sleeping. | ||
107 | */ | ||
108 | end = jiffies + msecs_to_jiffies(400); | ||
109 | while (time_before(jiffies, end)) { | ||
110 | i2c_smbus_write_byte(client, cmd); | ||
111 | |||
112 | if (loop++ < 5) | ||
113 | mdelay(1); | ||
114 | else | ||
115 | msleep(1); | ||
116 | |||
117 | ret = i2c_smbus_read_byte(client); | ||
118 | if (ret < 0) | ||
119 | return ret; | ||
120 | else if (ret & 0x0080) | ||
121 | break; | ||
122 | } | ||
123 | if (!(ret & 0x80)) | 103 | if (!(ret & 0x80)) |
124 | return -EIO; | 104 | return -EAGAIN; |
125 | return ret & 0x7f; /* remove the "valid" bit */ | 105 | return ret & 0x7f; /* remove the "valid" bit */ |
126 | } | 106 | } |
127 | 107 | ||
@@ -285,8 +265,6 @@ static ssize_t __tsl2550_show_lux(struct i2c_client *client, char *buf) | |||
285 | return ret; | 265 | return ret; |
286 | ch0 = ret; | 266 | ch0 = ret; |
287 | 267 | ||
288 | mdelay(1); | ||
289 | |||
290 | ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC1); | 268 | ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC1); |
291 | if (ret < 0) | 269 | if (ret < 0) |
292 | return ret; | 270 | return ret; |
@@ -345,11 +323,10 @@ static int tsl2550_init_client(struct i2c_client *client) | |||
345 | * Probe the chip. To do so we try to power up the device and then to | 323 | * Probe the chip. To do so we try to power up the device and then to |
346 | * read back the 0x03 code | 324 | * read back the 0x03 code |
347 | */ | 325 | */ |
348 | err = i2c_smbus_write_byte(client, TSL2550_POWER_UP); | 326 | err = i2c_smbus_read_byte_data(client, TSL2550_POWER_UP); |
349 | if (err < 0) | 327 | if (err < 0) |
350 | return err; | 328 | return err; |
351 | mdelay(1); | 329 | if (err != TSL2550_POWER_UP) |
352 | if (i2c_smbus_read_byte(client) != TSL2550_POWER_UP) | ||
353 | return -ENODEV; | 330 | return -ENODEV; |
354 | data->power_state = 1; | 331 | data->power_state = 1; |
355 | 332 | ||
@@ -374,7 +351,8 @@ static int __devinit tsl2550_probe(struct i2c_client *client, | |||
374 | struct tsl2550_data *data; | 351 | struct tsl2550_data *data; |
375 | int *opmode, err = 0; | 352 | int *opmode, err = 0; |
376 | 353 | ||
377 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) { | 354 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE |
355 | | I2C_FUNC_SMBUS_READ_BYTE_DATA)) { | ||
378 | err = -EIO; | 356 | err = -EIO; |
379 | goto exit; | 357 | goto exit; |
380 | } | 358 | } |