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>
This commit is contained in:
parent
27693ce5f3
commit
ac7809414f
|
@ -24,10 +24,9 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/delay.h>
|
|
||||||
|
|
||||||
#define TSL2550_DRV_NAME "tsl2550"
|
#define TSL2550_DRV_NAME "tsl2550"
|
||||||
#define DRIVER_VERSION "1.1.2"
|
#define DRIVER_VERSION "1.2"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Defines
|
* 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)
|
static int tsl2550_get_adc_value(struct i2c_client *client, u8 cmd)
|
||||||
{
|
{
|
||||||
unsigned long end;
|
int ret;
|
||||||
int loop = 0, ret = 0;
|
|
||||||
|
|
||||||
/*
|
ret = i2c_smbus_read_byte_data(client, cmd);
|
||||||
* Read ADC channel waiting at most 400ms (see data sheet for further
|
if (ret < 0)
|
||||||
* info).
|
return ret;
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
if (!(ret & 0x80))
|
if (!(ret & 0x80))
|
||||||
return -EIO;
|
return -EAGAIN;
|
||||||
return ret & 0x7f; /* remove the "valid" bit */
|
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;
|
return ret;
|
||||||
ch0 = ret;
|
ch0 = ret;
|
||||||
|
|
||||||
mdelay(1);
|
|
||||||
|
|
||||||
ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC1);
|
ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC1);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
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
|
* Probe the chip. To do so we try to power up the device and then to
|
||||||
* read back the 0x03 code
|
* 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)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
mdelay(1);
|
if (err != TSL2550_POWER_UP)
|
||||||
if (i2c_smbus_read_byte(client) != TSL2550_POWER_UP)
|
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
data->power_state = 1;
|
data->power_state = 1;
|
||||||
|
|
||||||
|
@ -374,7 +351,8 @@ static int __devinit tsl2550_probe(struct i2c_client *client,
|
||||||
struct tsl2550_data *data;
|
struct tsl2550_data *data;
|
||||||
int *opmode, err = 0;
|
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;
|
err = -EIO;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue