diff options
-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; |