diff options
| -rw-r--r-- | drivers/misc/Kconfig | 13 | ||||
| -rw-r--r-- | drivers/platform/x86/dell-laptop.c | 86 |
2 files changed, 62 insertions, 37 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 59f4ba1b7034..1a7a9fc50ea1 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
| @@ -248,19 +248,6 @@ config SGI_GRU_DEBUG | |||
| 248 | This option enables addition debugging code for the SGI GRU driver. If | 248 | This option enables addition debugging code for the SGI GRU driver. If |
| 249 | you are unsure, say N. | 249 | you are unsure, say N. |
| 250 | 250 | ||
| 251 | config DELL_LAPTOP | ||
| 252 | tristate "Dell Laptop Extras (EXPERIMENTAL)" | ||
| 253 | depends on X86 | ||
| 254 | depends on DCDBAS | ||
| 255 | depends on EXPERIMENTAL | ||
| 256 | depends on BACKLIGHT_CLASS_DEVICE | ||
| 257 | depends on RFKILL | ||
| 258 | depends on POWER_SUPPLY | ||
| 259 | default n | ||
| 260 | ---help--- | ||
| 261 | This driver adds support for rfkill and backlight control to Dell | ||
| 262 | laptops. | ||
| 263 | |||
| 264 | config ISL29003 | 251 | config ISL29003 |
| 265 | tristate "Intersil ISL29003 ambient light sensor" | 252 | tristate "Intersil ISL29003 ambient light sensor" |
| 266 | depends on I2C && SYSFS | 253 | depends on I2C && SYSFS |
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 74909c4aaeea..3780994dc8f2 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c | |||
| @@ -58,6 +58,14 @@ static int da_command_code; | |||
| 58 | static int da_num_tokens; | 58 | static int da_num_tokens; |
| 59 | static struct calling_interface_token *da_tokens; | 59 | static struct calling_interface_token *da_tokens; |
| 60 | 60 | ||
| 61 | static struct platform_driver platform_driver = { | ||
| 62 | .driver = { | ||
| 63 | .name = "dell-laptop", | ||
| 64 | .owner = THIS_MODULE, | ||
| 65 | } | ||
| 66 | }; | ||
| 67 | |||
| 68 | static struct platform_device *platform_device; | ||
| 61 | static struct backlight_device *dell_backlight_device; | 69 | static struct backlight_device *dell_backlight_device; |
| 62 | static struct rfkill *wifi_rfkill; | 70 | static struct rfkill *wifi_rfkill; |
| 63 | static struct rfkill *bluetooth_rfkill; | 71 | static struct rfkill *bluetooth_rfkill; |
| @@ -74,7 +82,7 @@ static const struct dmi_system_id __initdata dell_device_table[] = { | |||
| 74 | { } | 82 | { } |
| 75 | }; | 83 | }; |
| 76 | 84 | ||
| 77 | static void parse_da_table(const struct dmi_header *dm) | 85 | static void __init parse_da_table(const struct dmi_header *dm) |
| 78 | { | 86 | { |
| 79 | /* Final token is a terminator, so we don't want to copy it */ | 87 | /* Final token is a terminator, so we don't want to copy it */ |
| 80 | int tokens = (dm->length-11)/sizeof(struct calling_interface_token)-1; | 88 | int tokens = (dm->length-11)/sizeof(struct calling_interface_token)-1; |
| @@ -103,7 +111,7 @@ static void parse_da_table(const struct dmi_header *dm) | |||
| 103 | da_num_tokens += tokens; | 111 | da_num_tokens += tokens; |
| 104 | } | 112 | } |
| 105 | 113 | ||
| 106 | static void find_tokens(const struct dmi_header *dm, void *dummy) | 114 | static void __init find_tokens(const struct dmi_header *dm, void *dummy) |
| 107 | { | 115 | { |
| 108 | switch (dm->type) { | 116 | switch (dm->type) { |
| 109 | case 0xd4: /* Indexed IO */ | 117 | case 0xd4: /* Indexed IO */ |
| @@ -197,8 +205,8 @@ static void dell_rfkill_query(struct rfkill *rfkill, void *data) | |||
| 197 | dell_send_request(&buffer, 17, 11); | 205 | dell_send_request(&buffer, 17, 11); |
| 198 | status = buffer.output[1]; | 206 | status = buffer.output[1]; |
| 199 | 207 | ||
| 200 | if (status & BIT(bit)) | 208 | rfkill_set_sw_state(rfkill, !!(status & BIT(bit))); |
| 201 | rfkill_set_hw_state(rfkill, !!(status & BIT(16))); | 209 | rfkill_set_hw_state(rfkill, !(status & BIT(16))); |
| 202 | } | 210 | } |
| 203 | 211 | ||
| 204 | static const struct rfkill_ops dell_rfkill_ops = { | 212 | static const struct rfkill_ops dell_rfkill_ops = { |
| @@ -206,7 +214,7 @@ static const struct rfkill_ops dell_rfkill_ops = { | |||
| 206 | .query = dell_rfkill_query, | 214 | .query = dell_rfkill_query, |
| 207 | }; | 215 | }; |
| 208 | 216 | ||
| 209 | static int dell_setup_rfkill(void) | 217 | static int __init dell_setup_rfkill(void) |
| 210 | { | 218 | { |
| 211 | struct calling_interface_buffer buffer; | 219 | struct calling_interface_buffer buffer; |
| 212 | int status; | 220 | int status; |
| @@ -217,7 +225,8 @@ static int dell_setup_rfkill(void) | |||
| 217 | status = buffer.output[1]; | 225 | status = buffer.output[1]; |
| 218 | 226 | ||
| 219 | if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) { | 227 | if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) { |
| 220 | wifi_rfkill = rfkill_alloc("dell-wifi", NULL, RFKILL_TYPE_WLAN, | 228 | wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev, |
| 229 | RFKILL_TYPE_WLAN, | ||
| 221 | &dell_rfkill_ops, (void *) 1); | 230 | &dell_rfkill_ops, (void *) 1); |
| 222 | if (!wifi_rfkill) { | 231 | if (!wifi_rfkill) { |
| 223 | ret = -ENOMEM; | 232 | ret = -ENOMEM; |
| @@ -229,7 +238,8 @@ static int dell_setup_rfkill(void) | |||
| 229 | } | 238 | } |
| 230 | 239 | ||
| 231 | if ((status & (1<<3|1<<9)) == (1<<3|1<<9)) { | 240 | if ((status & (1<<3|1<<9)) == (1<<3|1<<9)) { |
| 232 | bluetooth_rfkill = rfkill_alloc("dell-bluetooth", NULL, | 241 | bluetooth_rfkill = rfkill_alloc("dell-bluetooth", |
| 242 | &platform_device->dev, | ||
| 233 | RFKILL_TYPE_BLUETOOTH, | 243 | RFKILL_TYPE_BLUETOOTH, |
| 234 | &dell_rfkill_ops, (void *) 2); | 244 | &dell_rfkill_ops, (void *) 2); |
| 235 | if (!bluetooth_rfkill) { | 245 | if (!bluetooth_rfkill) { |
| @@ -242,7 +252,9 @@ static int dell_setup_rfkill(void) | |||
| 242 | } | 252 | } |
| 243 | 253 | ||
| 244 | if ((status & (1<<4|1<<10)) == (1<<4|1<<10)) { | 254 | if ((status & (1<<4|1<<10)) == (1<<4|1<<10)) { |
| 245 | wwan_rfkill = rfkill_alloc("dell-wwan", NULL, RFKILL_TYPE_WWAN, | 255 | wwan_rfkill = rfkill_alloc("dell-wwan", |
| 256 | &platform_device->dev, | ||
| 257 | RFKILL_TYPE_WWAN, | ||
| 246 | &dell_rfkill_ops, (void *) 3); | 258 | &dell_rfkill_ops, (void *) 3); |
| 247 | if (!wwan_rfkill) { | 259 | if (!wwan_rfkill) { |
| 248 | ret = -ENOMEM; | 260 | ret = -ENOMEM; |
| @@ -268,6 +280,22 @@ err_wifi: | |||
| 268 | return ret; | 280 | return ret; |
| 269 | } | 281 | } |
| 270 | 282 | ||
| 283 | static void dell_cleanup_rfkill(void) | ||
| 284 | { | ||
| 285 | if (wifi_rfkill) { | ||
| 286 | rfkill_unregister(wifi_rfkill); | ||
| 287 | rfkill_destroy(wifi_rfkill); | ||
| 288 | } | ||
| 289 | if (bluetooth_rfkill) { | ||
| 290 | rfkill_unregister(bluetooth_rfkill); | ||
| 291 | rfkill_destroy(bluetooth_rfkill); | ||
| 292 | } | ||
| 293 | if (wwan_rfkill) { | ||
| 294 | rfkill_unregister(wwan_rfkill); | ||
| 295 | rfkill_destroy(wwan_rfkill); | ||
| 296 | } | ||
| 297 | } | ||
| 298 | |||
| 271 | static int dell_send_intensity(struct backlight_device *bd) | 299 | static int dell_send_intensity(struct backlight_device *bd) |
| 272 | { | 300 | { |
| 273 | struct calling_interface_buffer buffer; | 301 | struct calling_interface_buffer buffer; |
| @@ -326,11 +354,23 @@ static int __init dell_init(void) | |||
| 326 | return -ENODEV; | 354 | return -ENODEV; |
| 327 | } | 355 | } |
| 328 | 356 | ||
| 357 | ret = platform_driver_register(&platform_driver); | ||
| 358 | if (ret) | ||
| 359 | goto fail_platform_driver; | ||
| 360 | platform_device = platform_device_alloc("dell-laptop", -1); | ||
| 361 | if (!platform_device) { | ||
| 362 | ret = -ENOMEM; | ||
| 363 | goto fail_platform_device1; | ||
| 364 | } | ||
| 365 | ret = platform_device_add(platform_device); | ||
| 366 | if (ret) | ||
| 367 | goto fail_platform_device2; | ||
| 368 | |||
| 329 | ret = dell_setup_rfkill(); | 369 | ret = dell_setup_rfkill(); |
| 330 | 370 | ||
| 331 | if (ret) { | 371 | if (ret) { |
| 332 | printk(KERN_WARNING "dell-laptop: Unable to setup rfkill\n"); | 372 | printk(KERN_WARNING "dell-laptop: Unable to setup rfkill\n"); |
| 333 | goto out; | 373 | goto fail_rfkill; |
| 334 | } | 374 | } |
| 335 | 375 | ||
| 336 | #ifdef CONFIG_ACPI | 376 | #ifdef CONFIG_ACPI |
| @@ -352,13 +392,13 @@ static int __init dell_init(void) | |||
| 352 | if (max_intensity) { | 392 | if (max_intensity) { |
| 353 | dell_backlight_device = backlight_device_register( | 393 | dell_backlight_device = backlight_device_register( |
| 354 | "dell_backlight", | 394 | "dell_backlight", |
| 355 | NULL, NULL, | 395 | &platform_device->dev, NULL, |
| 356 | &dell_ops); | 396 | &dell_ops); |
| 357 | 397 | ||
| 358 | if (IS_ERR(dell_backlight_device)) { | 398 | if (IS_ERR(dell_backlight_device)) { |
| 359 | ret = PTR_ERR(dell_backlight_device); | 399 | ret = PTR_ERR(dell_backlight_device); |
| 360 | dell_backlight_device = NULL; | 400 | dell_backlight_device = NULL; |
| 361 | goto out; | 401 | goto fail_backlight; |
| 362 | } | 402 | } |
| 363 | 403 | ||
| 364 | dell_backlight_device->props.max_brightness = max_intensity; | 404 | dell_backlight_device->props.max_brightness = max_intensity; |
| @@ -368,13 +408,16 @@ static int __init dell_init(void) | |||
| 368 | } | 408 | } |
| 369 | 409 | ||
| 370 | return 0; | 410 | return 0; |
| 371 | out: | 411 | |
| 372 | if (wifi_rfkill) | 412 | fail_backlight: |
| 373 | rfkill_unregister(wifi_rfkill); | 413 | dell_cleanup_rfkill(); |
| 374 | if (bluetooth_rfkill) | 414 | fail_rfkill: |
| 375 | rfkill_unregister(bluetooth_rfkill); | 415 | platform_device_del(platform_device); |
| 376 | if (wwan_rfkill) | 416 | fail_platform_device2: |
| 377 | rfkill_unregister(wwan_rfkill); | 417 | platform_device_put(platform_device); |
| 418 | fail_platform_device1: | ||
| 419 | platform_driver_unregister(&platform_driver); | ||
| 420 | fail_platform_driver: | ||
| 378 | kfree(da_tokens); | 421 | kfree(da_tokens); |
| 379 | return ret; | 422 | return ret; |
| 380 | } | 423 | } |
| @@ -382,12 +425,7 @@ out: | |||
| 382 | static void __exit dell_exit(void) | 425 | static void __exit dell_exit(void) |
| 383 | { | 426 | { |
| 384 | backlight_device_unregister(dell_backlight_device); | 427 | backlight_device_unregister(dell_backlight_device); |
| 385 | if (wifi_rfkill) | 428 | dell_cleanup_rfkill(); |
| 386 | rfkill_unregister(wifi_rfkill); | ||
| 387 | if (bluetooth_rfkill) | ||
| 388 | rfkill_unregister(bluetooth_rfkill); | ||
| 389 | if (wwan_rfkill) | ||
| 390 | rfkill_unregister(wwan_rfkill); | ||
| 391 | } | 429 | } |
| 392 | 430 | ||
| 393 | module_init(dell_init); | 431 | module_init(dell_init); |
