diff options
author | Eric Piel <eric.piel@tremplin-utc.net> | 2009-06-16 18:34:14 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-16 22:47:57 -0400 |
commit | a002ee896dfd08ce9fba44e9ae513c9094699a27 (patch) | |
tree | 3a66ea80ad5523359e3f3f34be39d902d84706bb /drivers/hwmon | |
parent | c28842421cb6a29fd952043381bc5391bdf6be50 (diff) |
lis3: remove automatic shutdown of the device
After measurement on my laptop, it seems that turning off the device does
not bring any energy saving (within 0.1W precision). So let's keep the
device always on. It simplifies the code, and it avoids the problem of
reading a wrong value sometimes just after turning the device on.
Moreover, since commit ef2cfc790bf5f0ff189b01eabc0f4feb5e8524df had been
too zealous, the device was actually never turned off anyway. This patch
also restores the damages done by this commit concerning the
initialisation/poweroff.
Also do more clean up with the usage of the lis3_dev global variable.
Signed-off-by: Eric Piel <eric.piel@tremplin-utc.net>
Signed-off-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/hp_accel.c | 10 | ||||
-rw-r--r-- | drivers/hwmon/lis3lv02d.c | 88 | ||||
-rw-r--r-- | drivers/hwmon/lis3lv02d.h | 5 |
3 files changed, 32 insertions, 71 deletions
diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c index abca7e9f953b..0ebd0099e602 100644 --- a/drivers/hwmon/hp_accel.c +++ b/drivers/hwmon/hp_accel.c | |||
@@ -324,7 +324,7 @@ static int lis3lv02d_remove(struct acpi_device *device, int type) | |||
324 | flush_work(&hpled_led.work); | 324 | flush_work(&hpled_led.work); |
325 | led_classdev_unregister(&hpled_led.led_classdev); | 325 | led_classdev_unregister(&hpled_led.led_classdev); |
326 | 326 | ||
327 | return lis3lv02d_remove_fs(); | 327 | return lis3lv02d_remove_fs(&lis3_dev); |
328 | } | 328 | } |
329 | 329 | ||
330 | 330 | ||
@@ -338,13 +338,7 @@ static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state) | |||
338 | 338 | ||
339 | static int lis3lv02d_resume(struct acpi_device *device) | 339 | static int lis3lv02d_resume(struct acpi_device *device) |
340 | { | 340 | { |
341 | /* put back the device in the right state (ACPI might turn it on) */ | 341 | lis3lv02d_poweron(&lis3_dev); |
342 | mutex_lock(&lis3_dev.lock); | ||
343 | if (lis3_dev.usage > 0) | ||
344 | lis3lv02d_poweron(&lis3_dev); | ||
345 | else | ||
346 | lis3lv02d_poweroff(&lis3_dev); | ||
347 | mutex_unlock(&lis3_dev.lock); | ||
348 | return 0; | 342 | return 0; |
349 | } | 343 | } |
350 | #else | 344 | #else |
diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c index 17f200341bc1..df3f58613f7b 100644 --- a/drivers/hwmon/lis3lv02d.c +++ b/drivers/hwmon/lis3lv02d.c | |||
@@ -105,56 +105,39 @@ static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z) | |||
105 | { | 105 | { |
106 | int position[3]; | 106 | int position[3]; |
107 | 107 | ||
108 | position[0] = lis3_dev.read_data(lis3, OUTX); | 108 | position[0] = lis3->read_data(lis3, OUTX); |
109 | position[1] = lis3_dev.read_data(lis3, OUTY); | 109 | position[1] = lis3->read_data(lis3, OUTY); |
110 | position[2] = lis3_dev.read_data(lis3, OUTZ); | 110 | position[2] = lis3->read_data(lis3, OUTZ); |
111 | 111 | ||
112 | *x = lis3lv02d_get_axis(lis3_dev.ac.x, position); | 112 | *x = lis3lv02d_get_axis(lis3->ac.x, position); |
113 | *y = lis3lv02d_get_axis(lis3_dev.ac.y, position); | 113 | *y = lis3lv02d_get_axis(lis3->ac.y, position); |
114 | *z = lis3lv02d_get_axis(lis3_dev.ac.z, position); | 114 | *z = lis3lv02d_get_axis(lis3->ac.z, position); |
115 | } | 115 | } |
116 | 116 | ||
117 | void lis3lv02d_poweroff(struct lis3lv02d *lis3) | 117 | void lis3lv02d_poweroff(struct lis3lv02d *lis3) |
118 | { | 118 | { |
119 | lis3_dev.is_on = 0; | 119 | /* disable X,Y,Z axis and power down */ |
120 | lis3->write(lis3, CTRL_REG1, 0x00); | ||
120 | } | 121 | } |
121 | EXPORT_SYMBOL_GPL(lis3lv02d_poweroff); | 122 | EXPORT_SYMBOL_GPL(lis3lv02d_poweroff); |
122 | 123 | ||
123 | void lis3lv02d_poweron(struct lis3lv02d *lis3) | 124 | void lis3lv02d_poweron(struct lis3lv02d *lis3) |
124 | { | 125 | { |
125 | lis3_dev.is_on = 1; | 126 | u8 reg; |
126 | lis3_dev.init(lis3); | ||
127 | } | ||
128 | EXPORT_SYMBOL_GPL(lis3lv02d_poweron); | ||
129 | 127 | ||
130 | /* | 128 | lis3->init(lis3); |
131 | * To be called before starting to use the device. It makes sure that the | ||
132 | * device will always be on until a call to lis3lv02d_decrease_use(). Not to be | ||
133 | * used from interrupt context. | ||
134 | */ | ||
135 | static void lis3lv02d_increase_use(struct lis3lv02d *dev) | ||
136 | { | ||
137 | mutex_lock(&dev->lock); | ||
138 | dev->usage++; | ||
139 | if (dev->usage == 1) { | ||
140 | if (!dev->is_on) | ||
141 | lis3lv02d_poweron(dev); | ||
142 | } | ||
143 | mutex_unlock(&dev->lock); | ||
144 | } | ||
145 | 129 | ||
146 | /* | 130 | /* |
147 | * To be called whenever a usage of the device is stopped. | 131 | * Common configuration |
148 | * It will make sure to turn off the device when there is not usage. | 132 | * BDU: LSB and MSB values are not updated until both have been read. |
149 | */ | 133 | * So the value read will always be correct. |
150 | static void lis3lv02d_decrease_use(struct lis3lv02d *dev) | 134 | */ |
151 | { | 135 | lis3->read(lis3, CTRL_REG2, ®); |
152 | mutex_lock(&dev->lock); | 136 | reg |= CTRL2_BDU; |
153 | dev->usage--; | 137 | lis3->write(lis3, CTRL_REG2, reg); |
154 | if (dev->usage == 0) | ||
155 | lis3lv02d_poweroff(dev); | ||
156 | mutex_unlock(&dev->lock); | ||
157 | } | 138 | } |
139 | EXPORT_SYMBOL_GPL(lis3lv02d_poweron); | ||
140 | |||
158 | 141 | ||
159 | static irqreturn_t lis302dl_interrupt(int irq, void *dummy) | 142 | static irqreturn_t lis302dl_interrupt(int irq, void *dummy) |
160 | { | 143 | { |
@@ -198,14 +181,12 @@ static int lis3lv02d_misc_open(struct inode *inode, struct file *file) | |||
198 | printk(KERN_ERR DRIVER_NAME ": IRQ%d allocation failed\n", lis3_dev.irq); | 181 | printk(KERN_ERR DRIVER_NAME ": IRQ%d allocation failed\n", lis3_dev.irq); |
199 | return -EBUSY; | 182 | return -EBUSY; |
200 | } | 183 | } |
201 | lis3lv02d_increase_use(&lis3_dev); | ||
202 | return 0; | 184 | return 0; |
203 | } | 185 | } |
204 | 186 | ||
205 | static int lis3lv02d_misc_release(struct inode *inode, struct file *file) | 187 | static int lis3lv02d_misc_release(struct inode *inode, struct file *file) |
206 | { | 188 | { |
207 | fasync_helper(-1, file, 0, &lis3_dev.async_queue); | 189 | fasync_helper(-1, file, 0, &lis3_dev.async_queue); |
208 | lis3lv02d_decrease_use(&lis3_dev); | ||
209 | free_irq(lis3_dev.irq, &lis3_dev); | 190 | free_irq(lis3_dev.irq, &lis3_dev); |
210 | clear_bit(0, &lis3_dev.misc_opened); /* release the device */ | 191 | clear_bit(0, &lis3_dev.misc_opened); /* release the device */ |
211 | return 0; | 192 | return 0; |
@@ -314,10 +295,8 @@ static int lis3lv02d_joystick_kthread(void *data) | |||
314 | 295 | ||
315 | static int lis3lv02d_joystick_open(struct input_dev *input) | 296 | static int lis3lv02d_joystick_open(struct input_dev *input) |
316 | { | 297 | { |
317 | lis3lv02d_increase_use(&lis3_dev); | ||
318 | lis3_dev.kthread = kthread_run(lis3lv02d_joystick_kthread, NULL, "klis3lv02d"); | 298 | lis3_dev.kthread = kthread_run(lis3lv02d_joystick_kthread, NULL, "klis3lv02d"); |
319 | if (IS_ERR(lis3_dev.kthread)) { | 299 | if (IS_ERR(lis3_dev.kthread)) { |
320 | lis3lv02d_decrease_use(&lis3_dev); | ||
321 | return PTR_ERR(lis3_dev.kthread); | 300 | return PTR_ERR(lis3_dev.kthread); |
322 | } | 301 | } |
323 | 302 | ||
@@ -327,7 +306,6 @@ static int lis3lv02d_joystick_open(struct input_dev *input) | |||
327 | static void lis3lv02d_joystick_close(struct input_dev *input) | 306 | static void lis3lv02d_joystick_close(struct input_dev *input) |
328 | { | 307 | { |
329 | kthread_stop(lis3_dev.kthread); | 308 | kthread_stop(lis3_dev.kthread); |
330 | lis3lv02d_decrease_use(&lis3_dev); | ||
331 | } | 309 | } |
332 | 310 | ||
333 | static inline void lis3lv02d_calibrate_joystick(void) | 311 | static inline void lis3lv02d_calibrate_joystick(void) |
@@ -390,9 +368,7 @@ static ssize_t lis3lv02d_position_show(struct device *dev, | |||
390 | { | 368 | { |
391 | int x, y, z; | 369 | int x, y, z; |
392 | 370 | ||
393 | lis3lv02d_increase_use(&lis3_dev); | ||
394 | lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z); | 371 | lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z); |
395 | lis3lv02d_decrease_use(&lis3_dev); | ||
396 | return sprintf(buf, "(%d,%d,%d)\n", x, y, z); | 372 | return sprintf(buf, "(%d,%d,%d)\n", x, y, z); |
397 | } | 373 | } |
398 | 374 | ||
@@ -406,9 +382,7 @@ static ssize_t lis3lv02d_calibrate_store(struct device *dev, | |||
406 | struct device_attribute *attr, | 382 | struct device_attribute *attr, |
407 | const char *buf, size_t count) | 383 | const char *buf, size_t count) |
408 | { | 384 | { |
409 | lis3lv02d_increase_use(&lis3_dev); | ||
410 | lis3lv02d_calibrate_joystick(); | 385 | lis3lv02d_calibrate_joystick(); |
411 | lis3lv02d_decrease_use(&lis3_dev); | ||
412 | return count; | 386 | return count; |
413 | } | 387 | } |
414 | 388 | ||
@@ -420,9 +394,7 @@ static ssize_t lis3lv02d_rate_show(struct device *dev, | |||
420 | u8 ctrl; | 394 | u8 ctrl; |
421 | int val; | 395 | int val; |
422 | 396 | ||
423 | lis3lv02d_increase_use(&lis3_dev); | ||
424 | lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl); | 397 | lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl); |
425 | lis3lv02d_decrease_use(&lis3_dev); | ||
426 | val = (ctrl & (CTRL1_DF0 | CTRL1_DF1)) >> 4; | 398 | val = (ctrl & (CTRL1_DF0 | CTRL1_DF1)) >> 4; |
427 | return sprintf(buf, "%d\n", lis3lv02dl_df_val[val]); | 399 | return sprintf(buf, "%d\n", lis3lv02dl_df_val[val]); |
428 | } | 400 | } |
@@ -446,17 +418,17 @@ static struct attribute_group lis3lv02d_attribute_group = { | |||
446 | 418 | ||
447 | static int lis3lv02d_add_fs(struct lis3lv02d *lis3) | 419 | static int lis3lv02d_add_fs(struct lis3lv02d *lis3) |
448 | { | 420 | { |
449 | lis3_dev.pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); | 421 | lis3->pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); |
450 | if (IS_ERR(lis3_dev.pdev)) | 422 | if (IS_ERR(lis3->pdev)) |
451 | return PTR_ERR(lis3_dev.pdev); | 423 | return PTR_ERR(lis3->pdev); |
452 | 424 | ||
453 | return sysfs_create_group(&lis3_dev.pdev->dev.kobj, &lis3lv02d_attribute_group); | 425 | return sysfs_create_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group); |
454 | } | 426 | } |
455 | 427 | ||
456 | int lis3lv02d_remove_fs(void) | 428 | int lis3lv02d_remove_fs(struct lis3lv02d *lis3) |
457 | { | 429 | { |
458 | sysfs_remove_group(&lis3_dev.pdev->dev.kobj, &lis3lv02d_attribute_group); | 430 | sysfs_remove_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group); |
459 | platform_device_unregister(lis3_dev.pdev); | 431 | platform_device_unregister(lis3->pdev); |
460 | return 0; | 432 | return 0; |
461 | } | 433 | } |
462 | EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs); | 434 | EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs); |
@@ -482,13 +454,12 @@ int lis3lv02d_init_device(struct lis3lv02d *dev) | |||
482 | break; | 454 | break; |
483 | default: | 455 | default: |
484 | printk(KERN_ERR DRIVER_NAME | 456 | printk(KERN_ERR DRIVER_NAME |
485 | ": unknown sensor type 0x%X\n", lis3_dev.whoami); | 457 | ": unknown sensor type 0x%X\n", dev->whoami); |
486 | return -EINVAL; | 458 | return -EINVAL; |
487 | } | 459 | } |
488 | 460 | ||
489 | mutex_init(&dev->lock); | ||
490 | lis3lv02d_add_fs(dev); | 461 | lis3lv02d_add_fs(dev); |
491 | lis3lv02d_increase_use(dev); | 462 | lis3lv02d_poweron(dev); |
492 | 463 | ||
493 | if (lis3lv02d_joystick_enable()) | 464 | if (lis3lv02d_joystick_enable()) |
494 | printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n"); | 465 | printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n"); |
@@ -503,7 +474,6 @@ int lis3lv02d_init_device(struct lis3lv02d *dev) | |||
503 | if (misc_register(&lis3lv02d_misc_device)) | 474 | if (misc_register(&lis3lv02d_misc_device)) |
504 | printk(KERN_ERR DRIVER_NAME ": misc_register failed\n"); | 475 | printk(KERN_ERR DRIVER_NAME ": misc_register failed\n"); |
505 | out: | 476 | out: |
506 | lis3lv02d_decrease_use(dev); | ||
507 | return 0; | 477 | return 0; |
508 | } | 478 | } |
509 | EXPORT_SYMBOL_GPL(lis3lv02d_init_device); | 479 | EXPORT_SYMBOL_GPL(lis3lv02d_init_device); |
diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h index 745ec96806d4..b007d8184212 100644 --- a/drivers/hwmon/lis3lv02d.h +++ b/drivers/hwmon/lis3lv02d.h | |||
@@ -171,14 +171,11 @@ struct lis3lv02d { | |||
171 | 171 | ||
172 | struct input_dev *idev; /* input device */ | 172 | struct input_dev *idev; /* input device */ |
173 | struct task_struct *kthread; /* kthread for input */ | 173 | struct task_struct *kthread; /* kthread for input */ |
174 | struct mutex lock; | ||
175 | struct platform_device *pdev; /* platform device */ | 174 | struct platform_device *pdev; /* platform device */ |
176 | atomic_t count; /* interrupt count after last read */ | 175 | atomic_t count; /* interrupt count after last read */ |
177 | int xcalib; /* calibrated null value for x */ | 176 | int xcalib; /* calibrated null value for x */ |
178 | int ycalib; /* calibrated null value for y */ | 177 | int ycalib; /* calibrated null value for y */ |
179 | int zcalib; /* calibrated null value for z */ | 178 | int zcalib; /* calibrated null value for z */ |
180 | unsigned char is_on; /* whether the device is on or off */ | ||
181 | unsigned char usage; /* usage counter */ | ||
182 | struct axis_conversion ac; /* hw -> logical axis */ | 179 | struct axis_conversion ac; /* hw -> logical axis */ |
183 | 180 | ||
184 | u32 irq; /* IRQ number */ | 181 | u32 irq; /* IRQ number */ |
@@ -192,6 +189,6 @@ int lis3lv02d_joystick_enable(void); | |||
192 | void lis3lv02d_joystick_disable(void); | 189 | void lis3lv02d_joystick_disable(void); |
193 | void lis3lv02d_poweroff(struct lis3lv02d *lis3); | 190 | void lis3lv02d_poweroff(struct lis3lv02d *lis3); |
194 | void lis3lv02d_poweron(struct lis3lv02d *lis3); | 191 | void lis3lv02d_poweron(struct lis3lv02d *lis3); |
195 | int lis3lv02d_remove_fs(void); | 192 | int lis3lv02d_remove_fs(struct lis3lv02d *lis3); |
196 | 193 | ||
197 | extern struct lis3lv02d lis3_dev; | 194 | extern struct lis3lv02d lis3_dev; |