isl29023: add delayed work driven mode
This commit is contained in:
@@ -62,12 +62,15 @@ struct isl29023_data {
|
|||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
struct input_dev *input;
|
struct input_dev *input;
|
||||||
struct work_struct work;
|
struct work_struct work;
|
||||||
|
struct delayed_work polled_work;
|
||||||
struct workqueue_struct *workqueue;
|
struct workqueue_struct *workqueue;
|
||||||
char phys[32];
|
char phys[32];
|
||||||
u8 reg_cache[ISL29023_NUM_CACHABLE_REGS];
|
u8 reg_cache[ISL29023_NUM_CACHABLE_REGS];
|
||||||
u8 mode_before_suspend;
|
u8 mode_before_suspend;
|
||||||
u8 mode_before_interrupt;
|
u8 mode_before_interrupt;
|
||||||
u16 rext;
|
u16 rext;
|
||||||
|
u8 polled;
|
||||||
|
u16 poll_interval;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int gain_range[] = {
|
static int gain_range[] = {
|
||||||
@@ -286,10 +289,21 @@ static int isl29023_set_mode(struct i2c_client *client, int mode)
|
|||||||
/* power_state */
|
/* power_state */
|
||||||
static int isl29023_set_power_state(struct i2c_client *client, int state)
|
static int isl29023_set_power_state(struct i2c_client *client, int state)
|
||||||
{
|
{
|
||||||
return __isl29023_write_reg(client, ISL29023_COMMAND1,
|
struct isl29023_data *data = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
int rc = __isl29023_write_reg(client, ISL29023_COMMAND1,
|
||||||
ISL29023_MODE_MASK, ISL29023_MODE_SHIFT,
|
ISL29023_MODE_MASK, ISL29023_MODE_SHIFT,
|
||||||
state ?
|
state ?
|
||||||
ISL29023_ALS_ONCE_MODE : ISL29023_PD_MODE);
|
ISL29023_ALS_ONCE_MODE : ISL29023_PD_MODE);
|
||||||
|
|
||||||
|
if (data->polled) {
|
||||||
|
if (state)
|
||||||
|
schedule_delayed_work(&data->polled_work,
|
||||||
|
msecs_to_jiffies(data->poll_interval));
|
||||||
|
else
|
||||||
|
cancel_delayed_work_sync(&data->polled_work);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int isl29023_get_power_state(struct i2c_client *client)
|
static int isl29023_get_power_state(struct i2c_client *client)
|
||||||
@@ -587,7 +601,7 @@ static ssize_t isl29023_store_mode(struct device *dev,
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO,
|
static DEVICE_ATTR(mode, 0666,
|
||||||
isl29023_show_mode, isl29023_store_mode);
|
isl29023_show_mode, isl29023_store_mode);
|
||||||
|
|
||||||
|
|
||||||
@@ -612,10 +626,11 @@ static ssize_t isl29023_store_power_state(struct device *dev,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ret = isl29023_set_power_state(client, val);
|
ret = isl29023_set_power_state(client, val);
|
||||||
|
|
||||||
return ret ? ret : count;
|
return ret ? ret : count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEVICE_ATTR(power_state, S_IWUSR | S_IRUGO,
|
static DEVICE_ATTR(power_state, 0666,
|
||||||
isl29023_show_power_state, isl29023_store_power_state);
|
isl29023_show_power_state, isl29023_store_power_state);
|
||||||
|
|
||||||
/* lux */
|
/* lux */
|
||||||
@@ -818,25 +833,43 @@ static int isl29023_init_client(struct i2c_client *client)
|
|||||||
|
|
||||||
static void isl29023_work(struct work_struct *work)
|
static void isl29023_work(struct work_struct *work)
|
||||||
{
|
{
|
||||||
|
struct i2c_client *client;
|
||||||
|
int lux;
|
||||||
struct isl29023_data *data =
|
struct isl29023_data *data =
|
||||||
container_of(work, struct isl29023_data, work);
|
container_of(work, struct isl29023_data, work);
|
||||||
struct i2c_client *client = data->client;
|
|
||||||
int lux;
|
|
||||||
|
|
||||||
|
struct isl29023_data *data_polled =
|
||||||
|
container_of((struct delayed_work *)work, struct isl29023_data,
|
||||||
|
polled_work);
|
||||||
|
|
||||||
|
if (data_polled->polled)
|
||||||
|
data = data_polled;
|
||||||
|
|
||||||
|
client = data->client;
|
||||||
|
|
||||||
|
if (!data->polled) {
|
||||||
/* Clear interrupt flag */
|
/* Clear interrupt flag */
|
||||||
isl29023_set_int_flag(client, 0);
|
isl29023_set_int_flag(client, 0);
|
||||||
|
|
||||||
data->mode_before_interrupt = isl29023_get_mode(client);
|
data->mode_before_interrupt = isl29023_get_mode(client);
|
||||||
|
}
|
||||||
|
|
||||||
lux = isl29023_get_adc_value(client);
|
lux = isl29023_get_adc_value(client);
|
||||||
|
|
||||||
|
if (!data->polled) {
|
||||||
/* To clear the interrpt status */
|
/* To clear the interrpt status */
|
||||||
isl29023_set_power_state(client, ISL29023_PD_MODE);
|
isl29023_set_power_state(client, ISL29023_PD_MODE);
|
||||||
isl29023_set_mode(client, data->mode_before_interrupt);
|
isl29023_set_mode(client, data->mode_before_interrupt);
|
||||||
|
}
|
||||||
|
|
||||||
msleep(100);
|
msleep(100);
|
||||||
|
|
||||||
input_report_abs(data->input, ABS_MISC, lux);
|
input_report_abs(data->input, ABS_MISC, lux);
|
||||||
input_sync(data->input);
|
input_sync(data->input);
|
||||||
|
|
||||||
|
if(data->polled) {
|
||||||
|
schedule_delayed_work(&data->polled_work,
|
||||||
|
msecs_to_jiffies(data->poll_interval));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static irqreturn_t isl29023_irq_handler(int irq, void *handle)
|
static irqreturn_t isl29023_irq_handler(int irq, void *handle)
|
||||||
@@ -871,6 +904,8 @@ static int __devinit isl29023_probe(struct i2c_client *client,
|
|||||||
|
|
||||||
data->client = client;
|
data->client = client;
|
||||||
data->rext = ls_data->rext;
|
data->rext = ls_data->rext;
|
||||||
|
data->polled = ls_data->polled;
|
||||||
|
data->poll_interval = ls_data->poll_interval;
|
||||||
snprintf(data->phys, sizeof(data->phys),
|
snprintf(data->phys, sizeof(data->phys),
|
||||||
"%s", dev_name(&client->dev));
|
"%s", dev_name(&client->dev));
|
||||||
i2c_set_clientdata(client, data);
|
i2c_set_clientdata(client, data);
|
||||||
@@ -905,6 +940,7 @@ static int __devinit isl29023_probe(struct i2c_client *client,
|
|||||||
if (err)
|
if (err)
|
||||||
goto exit_free_input;
|
goto exit_free_input;
|
||||||
|
|
||||||
|
if (!data->polled) {
|
||||||
/* set irq type to edge falling */
|
/* set irq type to edge falling */
|
||||||
irq_set_irq_type(client->irq, IRQF_TRIGGER_FALLING);
|
irq_set_irq_type(client->irq, IRQF_TRIGGER_FALLING);
|
||||||
err = request_irq(client->irq, isl29023_irq_handler, 0,
|
err = request_irq(client->irq, isl29023_irq_handler, 0,
|
||||||
@@ -914,6 +950,9 @@ static int __devinit isl29023_probe(struct i2c_client *client,
|
|||||||
client->irq);
|
client->irq);
|
||||||
goto exit_free_input;
|
goto exit_free_input;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
INIT_DELAYED_WORK(&data->polled_work, isl29023_work);
|
||||||
|
}
|
||||||
|
|
||||||
data->workqueue = create_singlethread_workqueue("isl29023");
|
data->workqueue = create_singlethread_workqueue("isl29023");
|
||||||
INIT_WORK(&data->work, isl29023_work);
|
INIT_WORK(&data->work, isl29023_work);
|
||||||
@@ -939,6 +978,8 @@ static int __devexit isl29023_remove(struct i2c_client *client)
|
|||||||
{
|
{
|
||||||
struct isl29023_data *data = i2c_get_clientdata(client);
|
struct isl29023_data *data = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
if (data->polled)
|
||||||
|
cancel_delayed_work_sync(&data->polled_work);
|
||||||
cancel_work_sync(&data->work);
|
cancel_work_sync(&data->work);
|
||||||
destroy_workqueue(data->workqueue);
|
destroy_workqueue(data->workqueue);
|
||||||
free_irq(client->irq, data);
|
free_irq(client->irq, data);
|
||||||
|
|||||||
@@ -47,6 +47,8 @@
|
|||||||
struct isl29023_platform_data {
|
struct isl29023_platform_data {
|
||||||
char *vdd_reg;
|
char *vdd_reg;
|
||||||
int rext;
|
int rext;
|
||||||
|
int polled;
|
||||||
|
int poll_interval;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user