diff options
Diffstat (limited to 'drivers/hwmon/hp_accel.c')
-rw-r--r-- | drivers/hwmon/hp_accel.c | 124 |
1 files changed, 52 insertions, 72 deletions
diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c index 29c83b5b9697..55d3dc565be6 100644 --- a/drivers/hwmon/hp_accel.c +++ b/drivers/hwmon/hp_accel.c | |||
@@ -85,25 +85,31 @@ MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids); | |||
85 | 85 | ||
86 | /** | 86 | /** |
87 | * lis3lv02d_acpi_init - ACPI _INI method: initialize the device. | 87 | * lis3lv02d_acpi_init - ACPI _INI method: initialize the device. |
88 | * @handle: the handle of the device | 88 | * @lis3: pointer to the device struct |
89 | * | 89 | * |
90 | * Returns AE_OK on success. | 90 | * Returns 0 on success. |
91 | */ | 91 | */ |
92 | acpi_status lis3lv02d_acpi_init(acpi_handle handle) | 92 | int lis3lv02d_acpi_init(struct lis3lv02d *lis3) |
93 | { | 93 | { |
94 | return acpi_evaluate_object(handle, METHOD_NAME__INI, NULL, NULL); | 94 | struct acpi_device *dev = lis3->bus_priv; |
95 | if (acpi_evaluate_object(dev->handle, METHOD_NAME__INI, | ||
96 | NULL, NULL) != AE_OK) | ||
97 | return -EINVAL; | ||
98 | |||
99 | return 0; | ||
95 | } | 100 | } |
96 | 101 | ||
97 | /** | 102 | /** |
98 | * lis3lv02d_acpi_read - ACPI ALRD method: read a register | 103 | * lis3lv02d_acpi_read - ACPI ALRD method: read a register |
99 | * @handle: the handle of the device | 104 | * @lis3: pointer to the device struct |
100 | * @reg: the register to read | 105 | * @reg: the register to read |
101 | * @ret: result of the operation | 106 | * @ret: result of the operation |
102 | * | 107 | * |
103 | * Returns AE_OK on success. | 108 | * Returns 0 on success. |
104 | */ | 109 | */ |
105 | acpi_status lis3lv02d_acpi_read(acpi_handle handle, int reg, u8 *ret) | 110 | int lis3lv02d_acpi_read(struct lis3lv02d *lis3, int reg, u8 *ret) |
106 | { | 111 | { |
112 | struct acpi_device *dev = lis3->bus_priv; | ||
107 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; | 113 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; |
108 | struct acpi_object_list args = { 1, &arg0 }; | 114 | struct acpi_object_list args = { 1, &arg0 }; |
109 | unsigned long long lret; | 115 | unsigned long long lret; |
@@ -111,21 +117,22 @@ acpi_status lis3lv02d_acpi_read(acpi_handle handle, int reg, u8 *ret) | |||
111 | 117 | ||
112 | arg0.integer.value = reg; | 118 | arg0.integer.value = reg; |
113 | 119 | ||
114 | status = acpi_evaluate_integer(handle, "ALRD", &args, &lret); | 120 | status = acpi_evaluate_integer(dev->handle, "ALRD", &args, &lret); |
115 | *ret = lret; | 121 | *ret = lret; |
116 | return status; | 122 | return (status != AE_OK) ? -EINVAL : 0; |
117 | } | 123 | } |
118 | 124 | ||
119 | /** | 125 | /** |
120 | * lis3lv02d_acpi_write - ACPI ALWR method: write to a register | 126 | * lis3lv02d_acpi_write - ACPI ALWR method: write to a register |
121 | * @handle: the handle of the device | 127 | * @lis3: pointer to the device struct |
122 | * @reg: the register to write to | 128 | * @reg: the register to write to |
123 | * @val: the value to write | 129 | * @val: the value to write |
124 | * | 130 | * |
125 | * Returns AE_OK on success. | 131 | * Returns 0 on success. |
126 | */ | 132 | */ |
127 | acpi_status lis3lv02d_acpi_write(acpi_handle handle, int reg, u8 val) | 133 | int lis3lv02d_acpi_write(struct lis3lv02d *lis3, int reg, u8 val) |
128 | { | 134 | { |
135 | struct acpi_device *dev = lis3->bus_priv; | ||
129 | unsigned long long ret; /* Not used when writting */ | 136 | unsigned long long ret; /* Not used when writting */ |
130 | union acpi_object in_obj[2]; | 137 | union acpi_object in_obj[2]; |
131 | struct acpi_object_list args = { 2, in_obj }; | 138 | struct acpi_object_list args = { 2, in_obj }; |
@@ -135,12 +142,15 @@ acpi_status lis3lv02d_acpi_write(acpi_handle handle, int reg, u8 val) | |||
135 | in_obj[1].type = ACPI_TYPE_INTEGER; | 142 | in_obj[1].type = ACPI_TYPE_INTEGER; |
136 | in_obj[1].integer.value = val; | 143 | in_obj[1].integer.value = val; |
137 | 144 | ||
138 | return acpi_evaluate_integer(handle, "ALWR", &args, &ret); | 145 | if (acpi_evaluate_integer(dev->handle, "ALWR", &args, &ret) != AE_OK) |
146 | return -EINVAL; | ||
147 | |||
148 | return 0; | ||
139 | } | 149 | } |
140 | 150 | ||
141 | static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi) | 151 | static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi) |
142 | { | 152 | { |
143 | adev.ac = *((struct axis_conversion *)dmi->driver_data); | 153 | lis3_dev.ac = *((struct axis_conversion *)dmi->driver_data); |
144 | printk(KERN_INFO DRIVER_NAME ": hardware type %s found.\n", dmi->ident); | 154 | printk(KERN_INFO DRIVER_NAME ": hardware type %s found.\n", dmi->ident); |
145 | 155 | ||
146 | return 1; | 156 | return 1; |
@@ -187,6 +197,7 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = { | |||
187 | AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted), | 197 | AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted), |
188 | AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted), | 198 | AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted), |
189 | AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left), | 199 | AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left), |
200 | AXIS_DMI_MATCH("HP2140", "HP 2140", xy_swap_inverted), | ||
190 | AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd), | 201 | AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd), |
191 | AXIS_DMI_MATCH("NC673x", "HP Compaq 673", xy_rotated_left_usd), | 202 | AXIS_DMI_MATCH("NC673x", "HP Compaq 673", xy_rotated_left_usd), |
192 | AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right), | 203 | AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right), |
@@ -201,6 +212,8 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = { | |||
201 | PRODUCT_NAME, "HP Pavilion dv5", | 212 | PRODUCT_NAME, "HP Pavilion dv5", |
202 | BOARD_NAME, "3600", | 213 | BOARD_NAME, "3600", |
203 | y_inverted), | 214 | y_inverted), |
215 | AXIS_DMI_MATCH("DV7", "HP Pavilion dv7", x_inverted), | ||
216 | AXIS_DMI_MATCH("HP8710", "HP Compaq 8710", y_inverted), | ||
204 | { NULL, } | 217 | { NULL, } |
205 | /* Laptop models without axis info (yet): | 218 | /* Laptop models without axis info (yet): |
206 | * "NC6910" "HP Compaq 6910" | 219 | * "NC6910" "HP Compaq 6910" |
@@ -214,7 +227,7 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = { | |||
214 | 227 | ||
215 | static void hpled_set(struct delayed_led_classdev *led_cdev, enum led_brightness value) | 228 | static void hpled_set(struct delayed_led_classdev *led_cdev, enum led_brightness value) |
216 | { | 229 | { |
217 | acpi_handle handle = adev.device->handle; | 230 | struct acpi_device *dev = lis3_dev.bus_priv; |
218 | unsigned long long ret; /* Not used when writing */ | 231 | unsigned long long ret; /* Not used when writing */ |
219 | union acpi_object in_obj[1]; | 232 | union acpi_object in_obj[1]; |
220 | struct acpi_object_list args = { 1, in_obj }; | 233 | struct acpi_object_list args = { 1, in_obj }; |
@@ -222,7 +235,7 @@ static void hpled_set(struct delayed_led_classdev *led_cdev, enum led_brightness | |||
222 | in_obj[0].type = ACPI_TYPE_INTEGER; | 235 | in_obj[0].type = ACPI_TYPE_INTEGER; |
223 | in_obj[0].integer.value = !!value; | 236 | in_obj[0].integer.value = !!value; |
224 | 237 | ||
225 | acpi_evaluate_integer(handle, "ALED", &args, &ret); | 238 | acpi_evaluate_integer(dev->handle, "ALED", &args, &ret); |
226 | } | 239 | } |
227 | 240 | ||
228 | static struct delayed_led_classdev hpled_led = { | 241 | static struct delayed_led_classdev hpled_led = { |
@@ -254,28 +267,11 @@ static void lis3lv02d_enum_resources(struct acpi_device *device) | |||
254 | acpi_status status; | 267 | acpi_status status; |
255 | 268 | ||
256 | status = acpi_walk_resources(device->handle, METHOD_NAME__CRS, | 269 | status = acpi_walk_resources(device->handle, METHOD_NAME__CRS, |
257 | lis3lv02d_get_resource, &adev.irq); | 270 | lis3lv02d_get_resource, &lis3_dev.irq); |
258 | if (ACPI_FAILURE(status)) | 271 | if (ACPI_FAILURE(status)) |
259 | printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n"); | 272 | printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n"); |
260 | } | 273 | } |
261 | 274 | ||
262 | static s16 lis3lv02d_read_16(acpi_handle handle, int reg) | ||
263 | { | ||
264 | u8 lo, hi; | ||
265 | |||
266 | adev.read(handle, reg - 1, &lo); | ||
267 | adev.read(handle, reg, &hi); | ||
268 | /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */ | ||
269 | return (s16)((hi << 8) | lo); | ||
270 | } | ||
271 | |||
272 | static s16 lis3lv02d_read_8(acpi_handle handle, int reg) | ||
273 | { | ||
274 | s8 lo; | ||
275 | adev.read(handle, reg, &lo); | ||
276 | return lo; | ||
277 | } | ||
278 | |||
279 | static int lis3lv02d_add(struct acpi_device *device) | 275 | static int lis3lv02d_add(struct acpi_device *device) |
280 | { | 276 | { |
281 | int ret; | 277 | int ret; |
@@ -283,51 +279,35 @@ static int lis3lv02d_add(struct acpi_device *device) | |||
283 | if (!device) | 279 | if (!device) |
284 | return -EINVAL; | 280 | return -EINVAL; |
285 | 281 | ||
286 | adev.device = device; | 282 | lis3_dev.bus_priv = device; |
287 | adev.init = lis3lv02d_acpi_init; | 283 | lis3_dev.init = lis3lv02d_acpi_init; |
288 | adev.read = lis3lv02d_acpi_read; | 284 | lis3_dev.read = lis3lv02d_acpi_read; |
289 | adev.write = lis3lv02d_acpi_write; | 285 | lis3_dev.write = lis3lv02d_acpi_write; |
290 | strcpy(acpi_device_name(device), DRIVER_NAME); | 286 | strcpy(acpi_device_name(device), DRIVER_NAME); |
291 | strcpy(acpi_device_class(device), ACPI_MDPS_CLASS); | 287 | strcpy(acpi_device_class(device), ACPI_MDPS_CLASS); |
292 | device->driver_data = &adev; | 288 | device->driver_data = &lis3_dev; |
293 | 289 | ||
294 | lis3lv02d_acpi_read(device->handle, WHO_AM_I, &adev.whoami); | 290 | /* obtain IRQ number of our device from ACPI */ |
295 | switch (adev.whoami) { | 291 | lis3lv02d_enum_resources(device); |
296 | case LIS_DOUBLE_ID: | ||
297 | printk(KERN_INFO DRIVER_NAME ": 2-byte sensor found\n"); | ||
298 | adev.read_data = lis3lv02d_read_16; | ||
299 | adev.mdps_max_val = 2048; | ||
300 | break; | ||
301 | case LIS_SINGLE_ID: | ||
302 | printk(KERN_INFO DRIVER_NAME ": 1-byte sensor found\n"); | ||
303 | adev.read_data = lis3lv02d_read_8; | ||
304 | adev.mdps_max_val = 128; | ||
305 | break; | ||
306 | default: | ||
307 | printk(KERN_ERR DRIVER_NAME | ||
308 | ": unknown sensor type 0x%X\n", adev.whoami); | ||
309 | return -EINVAL; | ||
310 | } | ||
311 | 292 | ||
312 | /* If possible use a "standard" axes order */ | 293 | /* If possible use a "standard" axes order */ |
313 | if (dmi_check_system(lis3lv02d_dmi_ids) == 0) { | 294 | if (dmi_check_system(lis3lv02d_dmi_ids) == 0) { |
314 | printk(KERN_INFO DRIVER_NAME ": laptop model unknown, " | 295 | printk(KERN_INFO DRIVER_NAME ": laptop model unknown, " |
315 | "using default axes configuration\n"); | 296 | "using default axes configuration\n"); |
316 | adev.ac = lis3lv02d_axis_normal; | 297 | lis3_dev.ac = lis3lv02d_axis_normal; |
317 | } | 298 | } |
318 | 299 | ||
319 | INIT_WORK(&hpled_led.work, delayed_set_status_worker); | 300 | /* call the core layer do its init */ |
320 | ret = led_classdev_register(NULL, &hpled_led.led_classdev); | 301 | ret = lis3lv02d_init_device(&lis3_dev); |
321 | if (ret) | 302 | if (ret) |
322 | return ret; | 303 | return ret; |
323 | 304 | ||
324 | /* obtain IRQ number of our device from ACPI */ | 305 | INIT_WORK(&hpled_led.work, delayed_set_status_worker); |
325 | lis3lv02d_enum_resources(adev.device); | 306 | ret = led_classdev_register(NULL, &hpled_led.led_classdev); |
326 | |||
327 | ret = lis3lv02d_init_device(&adev); | ||
328 | if (ret) { | 307 | if (ret) { |
308 | lis3lv02d_joystick_disable(); | ||
309 | lis3lv02d_poweroff(&lis3_dev); | ||
329 | flush_work(&hpled_led.work); | 310 | flush_work(&hpled_led.work); |
330 | led_classdev_unregister(&hpled_led.led_classdev); | ||
331 | return ret; | 311 | return ret; |
332 | } | 312 | } |
333 | 313 | ||
@@ -340,7 +320,7 @@ static int lis3lv02d_remove(struct acpi_device *device, int type) | |||
340 | return -EINVAL; | 320 | return -EINVAL; |
341 | 321 | ||
342 | lis3lv02d_joystick_disable(); | 322 | lis3lv02d_joystick_disable(); |
343 | lis3lv02d_poweroff(device->handle); | 323 | lis3lv02d_poweroff(&lis3_dev); |
344 | 324 | ||
345 | flush_work(&hpled_led.work); | 325 | flush_work(&hpled_led.work); |
346 | led_classdev_unregister(&hpled_led.led_classdev); | 326 | led_classdev_unregister(&hpled_led.led_classdev); |
@@ -353,19 +333,19 @@ static int lis3lv02d_remove(struct acpi_device *device, int type) | |||
353 | static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state) | 333 | static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state) |
354 | { | 334 | { |
355 | /* make sure the device is off when we suspend */ | 335 | /* make sure the device is off when we suspend */ |
356 | lis3lv02d_poweroff(device->handle); | 336 | lis3lv02d_poweroff(&lis3_dev); |
357 | return 0; | 337 | return 0; |
358 | } | 338 | } |
359 | 339 | ||
360 | static int lis3lv02d_resume(struct acpi_device *device) | 340 | static int lis3lv02d_resume(struct acpi_device *device) |
361 | { | 341 | { |
362 | /* put back the device in the right state (ACPI might turn it on) */ | 342 | /* put back the device in the right state (ACPI might turn it on) */ |
363 | mutex_lock(&adev.lock); | 343 | mutex_lock(&lis3_dev.lock); |
364 | if (adev.usage > 0) | 344 | if (lis3_dev.usage > 0) |
365 | lis3lv02d_poweron(device->handle); | 345 | lis3lv02d_poweron(&lis3_dev); |
366 | else | 346 | else |
367 | lis3lv02d_poweroff(device->handle); | 347 | lis3lv02d_poweroff(&lis3_dev); |
368 | mutex_unlock(&adev.lock); | 348 | mutex_unlock(&lis3_dev.lock); |
369 | return 0; | 349 | return 0; |
370 | } | 350 | } |
371 | #else | 351 | #else |