aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Piel <eric.piel@tremplin-utc.net>2009-06-16 18:34:14 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-16 22:47:57 -0400
commita002ee896dfd08ce9fba44e9ae513c9094699a27 (patch)
tree3a66ea80ad5523359e3f3f34be39d902d84706bb
parentc28842421cb6a29fd952043381bc5391bdf6be50 (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>
-rw-r--r--drivers/hwmon/hp_accel.c10
-rw-r--r--drivers/hwmon/lis3lv02d.c88
-rw-r--r--drivers/hwmon/lis3lv02d.h5
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
339static int lis3lv02d_resume(struct acpi_device *device) 339static 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
117void lis3lv02d_poweroff(struct lis3lv02d *lis3) 117void 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}
121EXPORT_SYMBOL_GPL(lis3lv02d_poweroff); 122EXPORT_SYMBOL_GPL(lis3lv02d_poweroff);
122 123
123void lis3lv02d_poweron(struct lis3lv02d *lis3) 124void lis3lv02d_poweron(struct lis3lv02d *lis3)
124{ 125{
125 lis3_dev.is_on = 1; 126 u8 reg;
126 lis3_dev.init(lis3);
127}
128EXPORT_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 */
135static 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.
150static void lis3lv02d_decrease_use(struct lis3lv02d *dev) 134 */
151{ 135 lis3->read(lis3, CTRL_REG2, &reg);
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}
139EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
140
158 141
159static irqreturn_t lis302dl_interrupt(int irq, void *dummy) 142static 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
205static int lis3lv02d_misc_release(struct inode *inode, struct file *file) 187static 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
315static int lis3lv02d_joystick_open(struct input_dev *input) 296static 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)
327static void lis3lv02d_joystick_close(struct input_dev *input) 306static 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
333static inline void lis3lv02d_calibrate_joystick(void) 311static 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
447static int lis3lv02d_add_fs(struct lis3lv02d *lis3) 419static 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
456int lis3lv02d_remove_fs(void) 428int 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}
462EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs); 434EXPORT_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");
505out: 476out:
506 lis3lv02d_decrease_use(dev);
507 return 0; 477 return 0;
508} 478}
509EXPORT_SYMBOL_GPL(lis3lv02d_init_device); 479EXPORT_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);
192void lis3lv02d_joystick_disable(void); 189void lis3lv02d_joystick_disable(void);
193void lis3lv02d_poweroff(struct lis3lv02d *lis3); 190void lis3lv02d_poweroff(struct lis3lv02d *lis3);
194void lis3lv02d_poweron(struct lis3lv02d *lis3); 191void lis3lv02d_poweron(struct lis3lv02d *lis3);
195int lis3lv02d_remove_fs(void); 192int lis3lv02d_remove_fs(struct lis3lv02d *lis3);
196 193
197extern struct lis3lv02d lis3_dev; 194extern struct lis3lv02d lis3_dev;