aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorentin Chary <corentincj@iksaif.net>2011-11-26 04:59:59 -0500
committerMatthew Garrett <mjg@redhat.com>2012-03-20 12:02:05 -0400
commit5dea7a2094d5e60fe8f8ec4277d22d7ad6fa8c26 (patch)
tree116cff47022d348786be668d8c8c4b44c254c54a
parenta6df48943a408b493d1aa141791d614a529d484e (diff)
samsung-laptop: move code into init/exit functions
Create _init()/_exit() function for each subsystem, remove the local struct samsung_laptop * and only keep a struct platform_device * that can only be used in samsung_init() and samsung_exit(). Signed-off-by: Corentin Chary <corentincj@iksaif.net> Acked-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: Matthew Garrett <mjg@redhat.com>
-rw-r--r--drivers/platform/x86/samsung-laptop.c609
1 files changed, 360 insertions, 249 deletions
diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c
index c2a74bfc017c..1dd81d148cb7 100644
--- a/drivers/platform/x86/samsung-laptop.c
+++ b/drivers/platform/x86/samsung-laptop.c
@@ -226,14 +226,14 @@ struct samsung_laptop {
226 226
227 struct mutex sabi_mutex; 227 struct mutex sabi_mutex;
228 228
229 struct platform_device *pdev; 229 struct platform_device *platform_device;
230 struct backlight_device *backlight_device; 230 struct backlight_device *backlight_device;
231 struct rfkill *rfk; 231 struct rfkill *rfk;
232 232
233 bool has_stepping_quirk; 233 bool has_stepping_quirk;
234}; 234};
235 235
236static struct samsung_laptop *samsung; 236
237 237
238static bool force; 238static bool force;
239module_param(force, bool, 0); 239module_param(force, bool, 0);
@@ -244,7 +244,8 @@ static bool debug;
244module_param(debug, bool, S_IRUGO | S_IWUSR); 244module_param(debug, bool, S_IRUGO | S_IWUSR);
245MODULE_PARM_DESC(debug, "Debug enabled or not"); 245MODULE_PARM_DESC(debug, "Debug enabled or not");
246 246
247static int sabi_get_command(u8 command, struct sabi_retval *sretval) 247static int sabi_get_command(struct samsung_laptop *samsung,
248 u8 command, struct sabi_retval *sretval)
248{ 249{
249 const struct sabi_config *config = samsung->config; 250 const struct sabi_config *config = samsung->config;
250 int retval = 0; 251 int retval = 0;
@@ -291,7 +292,8 @@ exit:
291 292
292} 293}
293 294
294static int sabi_set_command(u8 command, u8 data) 295static int sabi_set_command(struct samsung_laptop *samsung,
296 u8 command, u8 data)
295{ 297{
296 const struct sabi_config *config = samsung->config; 298 const struct sabi_config *config = samsung->config;
297 int retval = 0; 299 int retval = 0;
@@ -326,53 +328,53 @@ static int sabi_set_command(u8 command, u8 data)
326 return retval; 328 return retval;
327} 329}
328 330
329static void test_backlight(void) 331static void test_backlight(struct samsung_laptop *samsung)
330{ 332{
331 const struct sabi_commands *commands = &samsung->config->commands; 333 const struct sabi_commands *commands = &samsung->config->commands;
332 struct sabi_retval sretval; 334 struct sabi_retval sretval;
333 335
334 sabi_get_command(commands->get_backlight, &sretval); 336 sabi_get_command(samsung, commands->get_backlight, &sretval);
335 printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]); 337 printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
336 338
337 sabi_set_command(commands->set_backlight, 0); 339 sabi_set_command(samsung, commands->set_backlight, 0);
338 printk(KERN_DEBUG "backlight should be off\n"); 340 printk(KERN_DEBUG "backlight should be off\n");
339 341
340 sabi_get_command(commands->get_backlight, &sretval); 342 sabi_get_command(samsung, commands->get_backlight, &sretval);
341 printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]); 343 printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
342 344
343 msleep(1000); 345 msleep(1000);
344 346
345 sabi_set_command(commands->set_backlight, 1); 347 sabi_set_command(samsung, commands->set_backlight, 1);
346 printk(KERN_DEBUG "backlight should be on\n"); 348 printk(KERN_DEBUG "backlight should be on\n");
347 349
348 sabi_get_command(commands->get_backlight, &sretval); 350 sabi_get_command(samsung, commands->get_backlight, &sretval);
349 printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]); 351 printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
350} 352}
351 353
352static void test_wireless(void) 354static void test_wireless(struct samsung_laptop *samsung)
353{ 355{
354 const struct sabi_commands *commands = &samsung->config->commands; 356 const struct sabi_commands *commands = &samsung->config->commands;
355 struct sabi_retval sretval; 357 struct sabi_retval sretval;
356 358
357 sabi_get_command(commands->get_wireless_button, &sretval); 359 sabi_get_command(samsung, commands->get_wireless_button, &sretval);
358 printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]); 360 printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
359 361
360 sabi_set_command(commands->set_wireless_button, 0); 362 sabi_set_command(samsung, commands->set_wireless_button, 0);
361 printk(KERN_DEBUG "wireless led should be off\n"); 363 printk(KERN_DEBUG "wireless led should be off\n");
362 364
363 sabi_get_command(commands->get_wireless_button, &sretval); 365 sabi_get_command(samsung, commands->get_wireless_button, &sretval);
364 printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]); 366 printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
365 367
366 msleep(1000); 368 msleep(1000);
367 369
368 sabi_set_command(commands->set_wireless_button, 1); 370 sabi_set_command(samsung, commands->set_wireless_button, 1);
369 printk(KERN_DEBUG "wireless led should be on\n"); 371 printk(KERN_DEBUG "wireless led should be on\n");
370 372
371 sabi_get_command(commands->get_wireless_button, &sretval); 373 sabi_get_command(samsung, commands->get_wireless_button, &sretval);
372 printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]); 374 printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
373} 375}
374 376
375static u8 read_brightness(void) 377static int read_brightness(struct samsung_laptop *samsung)
376{ 378{
377 const struct sabi_config *config = samsung->config; 379 const struct sabi_config *config = samsung->config;
378 const struct sabi_commands *commands = &samsung->config->commands; 380 const struct sabi_commands *commands = &samsung->config->commands;
@@ -380,7 +382,7 @@ static u8 read_brightness(void)
380 int user_brightness = 0; 382 int user_brightness = 0;
381 int retval; 383 int retval;
382 384
383 retval = sabi_get_command(commands->get_brightness, 385 retval = sabi_get_command(samsung, commands->get_brightness,
384 &sretval); 386 &sretval);
385 if (!retval) { 387 if (!retval) {
386 user_brightness = sretval.retval[0]; 388 user_brightness = sretval.retval[0];
@@ -392,7 +394,7 @@ static u8 read_brightness(void)
392 return user_brightness; 394 return user_brightness;
393} 395}
394 396
395static void set_brightness(u8 user_brightness) 397static void set_brightness(struct samsung_laptop *samsung, u8 user_brightness)
396{ 398{
397 const struct sabi_config *config = samsung->config; 399 const struct sabi_config *config = samsung->config;
398 const struct sabi_commands *commands = &samsung->config->commands; 400 const struct sabi_commands *commands = &samsung->config->commands;
@@ -403,25 +405,27 @@ static void set_brightness(u8 user_brightness)
403 * short circuit if the specified level is what's already set 405 * short circuit if the specified level is what's already set
404 * to prevent the screen from flickering needlessly 406 * to prevent the screen from flickering needlessly
405 */ 407 */
406 if (user_brightness == read_brightness()) 408 if (user_brightness == read_brightness(samsung))
407 return; 409 return;
408 410
409 sabi_set_command(commands->set_brightness, 0); 411 sabi_set_command(samsung, commands->set_brightness, 0);
410 } 412 }
411 413
412 sabi_set_command(commands->set_brightness, user_level); 414 sabi_set_command(samsung, commands->set_brightness, user_level);
413} 415}
414 416
415static int get_brightness(struct backlight_device *bd) 417static int get_brightness(struct backlight_device *bd)
416{ 418{
417 return (int)read_brightness(); 419 struct samsung_laptop *samsung = bl_get_data(bd);
420
421 return read_brightness(samsung);
418} 422}
419 423
420static void check_for_stepping_quirk(void) 424static void check_for_stepping_quirk(struct samsung_laptop *samsung)
421{ 425{
422 u8 initial_level; 426 int initial_level;
423 u8 check_level; 427 int check_level;
424 u8 orig_level = read_brightness(); 428 int orig_level = read_brightness(samsung);
425 429
426 /* 430 /*
427 * Some laptops exhibit the strange behaviour of stepping toward 431 * Some laptops exhibit the strange behaviour of stepping toward
@@ -431,9 +435,9 @@ static void check_for_stepping_quirk(void)
431 */ 435 */
432 436
433 if (orig_level == 0) 437 if (orig_level == 0)
434 set_brightness(1); 438 set_brightness(samsung, 1);
435 439
436 initial_level = read_brightness(); 440 initial_level = read_brightness(samsung);
437 441
438 if (initial_level <= 2) 442 if (initial_level <= 2)
439 check_level = initial_level + 2; 443 check_level = initial_level + 2;
@@ -441,26 +445,28 @@ static void check_for_stepping_quirk(void)
441 check_level = initial_level - 2; 445 check_level = initial_level - 2;
442 446
443 samsung->has_stepping_quirk = false; 447 samsung->has_stepping_quirk = false;
444 set_brightness(check_level); 448 set_brightness(samsung, check_level);
445 449
446 if (read_brightness() != check_level) { 450 if (read_brightness(samsung) != check_level) {
447 samsung->has_stepping_quirk = true; 451 samsung->has_stepping_quirk = true;
448 pr_info("enabled workaround for brightness stepping quirk\n"); 452 pr_info("enabled workaround for brightness stepping quirk\n");
449 } 453 }
450 454
451 set_brightness(orig_level); 455 set_brightness(samsung, orig_level);
452} 456}
453 457
454static int update_status(struct backlight_device *bd) 458static int update_status(struct backlight_device *bd)
455{ 459{
460 struct samsung_laptop *samsung = bl_get_data(bd);
456 const struct sabi_commands *commands = &samsung->config->commands; 461 const struct sabi_commands *commands = &samsung->config->commands;
457 462
458 set_brightness(bd->props.brightness); 463 set_brightness(samsung, bd->props.brightness);
459 464
460 if (bd->props.power == FB_BLANK_UNBLANK) 465 if (bd->props.power == FB_BLANK_UNBLANK)
461 sabi_set_command(commands->set_backlight, 1); 466 sabi_set_command(samsung, commands->set_backlight, 1);
462 else 467 else
463 sabi_set_command(commands->set_backlight, 0); 468 sabi_set_command(samsung, commands->set_backlight, 0);
469
464 return 0; 470 return 0;
465} 471}
466 472
@@ -471,6 +477,7 @@ static const struct backlight_ops backlight_ops = {
471 477
472static int rfkill_set(void *data, bool blocked) 478static int rfkill_set(void *data, bool blocked)
473{ 479{
480 struct samsung_laptop *samsung = data;
474 const struct sabi_commands *commands = &samsung->config->commands; 481 const struct sabi_commands *commands = &samsung->config->commands;
475 482
476 /* Do something with blocked...*/ 483 /* Do something with blocked...*/
@@ -479,9 +486,9 @@ static int rfkill_set(void *data, bool blocked)
479 * blocked == true is off 486 * blocked == true is off
480 */ 487 */
481 if (blocked) 488 if (blocked)
482 sabi_set_command(commands->set_wireless_button, 0); 489 sabi_set_command(samsung, commands->set_wireless_button, 0);
483 else 490 else
484 sabi_set_command(commands->set_wireless_button, 1); 491 sabi_set_command(samsung, commands->set_wireless_button, 1);
485 492
486 return 0; 493 return 0;
487} 494}
@@ -490,40 +497,18 @@ static struct rfkill_ops rfkill_ops = {
490 .set_block = rfkill_set, 497 .set_block = rfkill_set,
491}; 498};
492 499
493static int init_wireless(struct platform_device *pdev)
494{
495 int retval;
496
497 samsung->rfk = rfkill_alloc("samsung-wifi", &samsung->pdev->dev, RFKILL_TYPE_WLAN,
498 &rfkill_ops, NULL);
499 if (!samsung->rfk)
500 return -ENOMEM;
501
502 retval = rfkill_register(samsung->rfk);
503 if (retval) {
504 rfkill_destroy(samsung->rfk);
505 return -ENODEV;
506 }
507
508 return 0;
509}
510
511static void destroy_wireless(void)
512{
513 rfkill_unregister(samsung->rfk);
514 rfkill_destroy(samsung->rfk);
515}
516
517static ssize_t get_performance_level(struct device *dev, 500static ssize_t get_performance_level(struct device *dev,
518 struct device_attribute *attr, char *buf) 501 struct device_attribute *attr, char *buf)
519{ 502{
503 struct samsung_laptop *samsung = dev_get_drvdata(dev);
520 const struct sabi_config *config = samsung->config; 504 const struct sabi_config *config = samsung->config;
505 const struct sabi_commands *commands = &config->commands;
521 struct sabi_retval sretval; 506 struct sabi_retval sretval;
522 int retval; 507 int retval;
523 int i; 508 int i;
524 509
525 /* Read the state */ 510 /* Read the state */
526 retval = sabi_get_command(config->commands.get_performance_level, 511 retval = sabi_get_command(samsung, commands->get_performance_level,
527 &sretval); 512 &sretval);
528 if (retval) 513 if (retval)
529 return retval; 514 return retval;
@@ -540,32 +525,285 @@ static ssize_t set_performance_level(struct device *dev,
540 struct device_attribute *attr, const char *buf, 525 struct device_attribute *attr, const char *buf,
541 size_t count) 526 size_t count)
542{ 527{
528 struct samsung_laptop *samsung = dev_get_drvdata(dev);
543 const struct sabi_config *config = samsung->config; 529 const struct sabi_config *config = samsung->config;
530 const struct sabi_commands *commands = &config->commands;
531 int i;
544 532
545 if (count >= 1) { 533 if (count < 1)
546 int i; 534 return count;
547 for (i = 0; config->performance_levels[i].name; ++i) { 535
548 const struct sabi_performance_level *level = 536 for (i = 0; config->performance_levels[i].name; ++i) {
549 &config->performance_levels[i]; 537 const struct sabi_performance_level *level =
550 if (!strncasecmp(level->name, buf, strlen(level->name))) { 538 &config->performance_levels[i];
551 sabi_set_command(config->commands.set_performance_level, 539 if (!strncasecmp(level->name, buf, strlen(level->name))) {
552 level->value); 540 sabi_set_command(samsung,
553 break; 541 commands->set_performance_level,
554 } 542 level->value);
543 break;
555 } 544 }
556 if (!config->performance_levels[i].name)
557 return -EINVAL;
558 } 545 }
546
547 if (!config->performance_levels[i].name)
548 return -EINVAL;
549
559 return count; 550 return count;
560} 551}
552
561static DEVICE_ATTR(performance_level, S_IWUSR | S_IRUGO, 553static DEVICE_ATTR(performance_level, S_IWUSR | S_IRUGO,
562 get_performance_level, set_performance_level); 554 get_performance_level, set_performance_level);
563 555
564 556
557static int find_signature(void __iomem *memcheck, const char *testStr)
558{
559 int i = 0;
560 int loca;
561
562 for (loca = 0; loca < 0xffff; loca++) {
563 char temp = readb(memcheck + loca);
564
565 if (temp == testStr[i]) {
566 if (i == strlen(testStr)-1)
567 break;
568 ++i;
569 } else {
570 i = 0;
571 }
572 }
573 return loca;
574}
575
576static void samsung_rfkill_exit(struct samsung_laptop *samsung)
577{
578 if (samsung->rfk) {
579 rfkill_unregister(samsung->rfk);
580 rfkill_destroy(samsung->rfk);
581 samsung->rfk = NULL;
582 }
583}
584
585static int __init samsung_rfkill_init(struct samsung_laptop *samsung)
586{
587 int retval;
588
589 samsung->rfk = rfkill_alloc("samsung-wifi",
590 &samsung->platform_device->dev,
591 RFKILL_TYPE_WLAN,
592 &rfkill_ops, samsung);
593 if (!samsung->rfk)
594 return -ENOMEM;
595
596 retval = rfkill_register(samsung->rfk);
597 if (retval) {
598 rfkill_destroy(samsung->rfk);
599 samsung->rfk = NULL;
600 return -ENODEV;
601 }
602
603 return 0;
604}
605
606static void samsung_backlight_exit(struct samsung_laptop *samsung)
607{
608 if (samsung->backlight_device) {
609 backlight_device_unregister(samsung->backlight_device);
610 samsung->backlight_device = NULL;
611 }
612}
613
614static int __init samsung_backlight_init(struct samsung_laptop *samsung)
615{
616 struct backlight_device *bd;
617 struct backlight_properties props;
618
619 memset(&props, 0, sizeof(struct backlight_properties));
620 props.type = BACKLIGHT_PLATFORM;
621 props.max_brightness = samsung->config->max_brightness -
622 samsung->config->min_brightness;
623
624 bd = backlight_device_register("samsung",
625 &samsung->platform_device->dev,
626 samsung, &backlight_ops,
627 &props);
628 if (IS_ERR(bd))
629 return PTR_ERR(bd);
630
631 samsung->backlight_device = bd;
632 samsung->backlight_device->props.brightness = read_brightness(samsung);
633 samsung->backlight_device->props.power = FB_BLANK_UNBLANK;
634 backlight_update_status(samsung->backlight_device);
635
636 return 0;
637}
638
639static void samsung_sysfs_exit(struct samsung_laptop *samsung)
640{
641 device_remove_file(&samsung->platform_device->dev,
642 &dev_attr_performance_level);
643}
644
645static int __init samsung_sysfs_init(struct samsung_laptop *samsung)
646{
647 return device_create_file(&samsung->platform_device->dev,
648 &dev_attr_performance_level);
649}
650
651static void samsung_sabi_exit(struct samsung_laptop *samsung)
652{
653 const struct sabi_config *config = samsung->config;
654
655 /* Turn off "Linux" mode in the BIOS */
656 if (config && config->commands.set_linux != 0xff)
657 sabi_set_command(samsung, config->commands.set_linux, 0x80);
658
659 if (samsung->sabi_iface) {
660 iounmap(samsung->sabi_iface);
661 samsung->sabi_iface = NULL;
662 }
663 if (samsung->f0000_segment) {
664 iounmap(samsung->f0000_segment);
665 samsung->f0000_segment = NULL;
666 }
667
668 samsung->config = NULL;
669}
670
671static __init void samsung_sabi_infos(struct samsung_laptop *samsung, int loca)
672{
673 const struct sabi_config *config = samsung->config;
674
675 printk(KERN_DEBUG "This computer supports SABI==%x\n",
676 loca + 0xf0000 - 6);
677 printk(KERN_DEBUG "SABI header:\n");
678 printk(KERN_DEBUG " SMI Port Number = 0x%04x\n",
679 readw(samsung->sabi + config->header_offsets.port));
680 printk(KERN_DEBUG " SMI Interface Function = 0x%02x\n",
681 readb(samsung->sabi + config->header_offsets.iface_func));
682 printk(KERN_DEBUG " SMI enable memory buffer = 0x%02x\n",
683 readb(samsung->sabi + config->header_offsets.en_mem));
684 printk(KERN_DEBUG " SMI restore memory buffer = 0x%02x\n",
685 readb(samsung->sabi + config->header_offsets.re_mem));
686 printk(KERN_DEBUG " SABI data offset = 0x%04x\n",
687 readw(samsung->sabi + config->header_offsets.data_offset));
688 printk(KERN_DEBUG " SABI data segment = 0x%04x\n",
689 readw(samsung->sabi + config->header_offsets.data_segment));
690}
691
692static void __init samsung_sabi_selftest(struct samsung_laptop *samsung,
693 unsigned int ifaceP)
694{
695 const struct sabi_config *config = samsung->config;
696 struct sabi_retval sretval;
697
698 printk(KERN_DEBUG "ifaceP = 0x%08x\n", ifaceP);
699 printk(KERN_DEBUG "sabi_iface = %p\n", samsung->sabi_iface);
700
701 test_backlight(samsung);
702 test_wireless(samsung);
703
704 sabi_get_command(samsung, config->commands.get_brightness, &sretval);
705 printk(KERN_DEBUG "brightness = 0x%02x\n", sretval.retval[0]);
706}
707
708static int __init samsung_sabi_init(struct samsung_laptop *samsung)
709{
710 const struct sabi_config *config = NULL;
711 const struct sabi_commands *commands;
712 unsigned int ifaceP;
713 int ret = 0;
714 int i;
715 int loca;
716
717 samsung->f0000_segment = ioremap_nocache(0xf0000, 0xffff);
718 if (!samsung->f0000_segment) {
719 pr_err("Can't map the segment at 0xf0000\n");
720 ret = -EINVAL;
721 goto exit;
722 }
723
724 /* Try to find one of the signatures in memory to find the header */
725 for (i = 0; sabi_configs[i].test_string != 0; ++i) {
726 samsung->config = &sabi_configs[i];
727 loca = find_signature(samsung->f0000_segment,
728 samsung->config->test_string);
729 if (loca != 0xffff)
730 break;
731 }
732
733 if (loca == 0xffff) {
734 pr_err("This computer does not support SABI\n");
735 ret = -ENODEV;
736 goto exit;
737 }
738
739 config = samsung->config;
740 commands = &config->commands;
741
742 /* point to the SMI port Number */
743 loca += 1;
744 samsung->sabi = (samsung->f0000_segment + loca);
745
746 if (debug)
747 samsung_sabi_infos(samsung, loca);
748
749 /* Get a pointer to the SABI Interface */
750 ifaceP = (readw(samsung->sabi + config->header_offsets.data_segment) & 0x0ffff) << 4;
751 ifaceP += readw(samsung->sabi + config->header_offsets.data_offset) & 0x0ffff;
752 samsung->sabi_iface = ioremap_nocache(ifaceP, 16);
753 if (!samsung->sabi_iface) {
754 pr_err("Can't remap %x\n", ifaceP);
755 ret = -EINVAL;
756 goto exit;
757 }
758
759 if (debug)
760 samsung_sabi_selftest(samsung, ifaceP);
761
762 /* Turn on "Linux" mode in the BIOS */
763 if (commands->set_linux != 0xff) {
764 int retval = sabi_set_command(samsung,
765 commands->set_linux, 0x81);
766 if (retval) {
767 pr_warn("Linux mode was not set!\n");
768 ret = -ENODEV;
769 goto exit;
770 }
771 }
772
773 /* Check for stepping quirk */
774 check_for_stepping_quirk(samsung);
775
776exit:
777 if (ret)
778 samsung_sabi_exit(samsung);
779
780 return ret;
781}
782
783static void samsung_platform_exit(struct samsung_laptop *samsung)
784{
785 if (samsung->platform_device) {
786 platform_device_unregister(samsung->platform_device);
787 samsung->platform_device = NULL;
788 }
789}
790
791static int __init samsung_platform_init(struct samsung_laptop *samsung)
792{
793 struct platform_device *pdev;
794
795 pdev = platform_device_register_simple("samsung", -1, NULL, 0);
796 if (IS_ERR(pdev))
797 return PTR_ERR(pdev);
798
799 samsung->platform_device = pdev;
800 platform_set_drvdata(samsung->platform_device, samsung);
801 return 0;
802}
803
565static int __init dmi_check_cb(const struct dmi_system_id *id) 804static int __init dmi_check_cb(const struct dmi_system_id *id)
566{ 805{
567 pr_info("found laptop model '%s'\n", 806 pr_info("found laptop model '%s'\n", id->ident);
568 id->ident);
569 return 1; 807 return 1;
570} 808}
571 809
@@ -806,36 +1044,12 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
806}; 1044};
807MODULE_DEVICE_TABLE(dmi, samsung_dmi_table); 1045MODULE_DEVICE_TABLE(dmi, samsung_dmi_table);
808 1046
809static int find_signature(void __iomem *memcheck, const char *testStr) 1047static struct platform_device *samsung_platform_device;
810{
811 int i = 0;
812 int loca;
813
814 for (loca = 0; loca < 0xffff; loca++) {
815 char temp = readb(memcheck + loca);
816
817 if (temp == testStr[i]) {
818 if (i == strlen(testStr)-1)
819 break;
820 ++i;
821 } else {
822 i = 0;
823 }
824 }
825 return loca;
826}
827 1048
828static int __init samsung_init(void) 1049static int __init samsung_init(void)
829{ 1050{
830 const struct sabi_config *config = NULL; 1051 struct samsung_laptop *samsung;
831 const struct sabi_commands *commands; 1052 int ret;
832 struct backlight_device *bd;
833 struct backlight_properties props;
834 struct sabi_retval sretval;
835 unsigned int ifaceP;
836 int i;
837 int loca;
838 int retval;
839 1053
840 if (!force && !dmi_check_system(samsung_dmi_table)) 1054 if (!force && !dmi_check_system(samsung_dmi_table))
841 return -ENODEV; 1055 return -ENODEV;
@@ -846,159 +1060,56 @@ static int __init samsung_init(void)
846 1060
847 mutex_init(&samsung->sabi_mutex); 1061 mutex_init(&samsung->sabi_mutex);
848 1062
849 samsung->f0000_segment = ioremap_nocache(0xf0000, 0xffff); 1063 ret = samsung_platform_init(samsung);
850 if (!samsung->f0000_segment) { 1064 if (ret)
851 pr_err("Can't map the segment at 0xf0000\n"); 1065 goto error_platform;
852 goto error_cant_map; 1066
853 } 1067 ret = samsung_sabi_init(samsung);
854 1068 if (ret)
855 /* Try to find one of the signatures in memory to find the header */ 1069 goto error_sabi;
856 for (i = 0; sabi_configs[i].test_string != 0; ++i) { 1070
857 samsung->config = &sabi_configs[i]; 1071 ret = samsung_sysfs_init(samsung);
858 loca = find_signature(samsung->f0000_segment, 1072 if (ret)
859 samsung->config->test_string); 1073 goto error_sysfs;
860 if (loca != 0xffff) 1074
861 break; 1075 ret = samsung_backlight_init(samsung);
862 } 1076 if (ret)
863 1077 goto error_backlight;
864 if (loca == 0xffff) { 1078
865 pr_err("This computer does not support SABI\n"); 1079 ret = samsung_rfkill_init(samsung);
866 goto error_no_signature; 1080 if (ret)
867 } 1081 goto error_rfkill;
868 1082
869 config = samsung->config; 1083 samsung_platform_device = samsung->platform_device;
870 commands = &config->commands; 1084 return ret;
871 1085
872 /* point to the SMI port Number */ 1086error_rfkill:
873 loca += 1; 1087 samsung_backlight_exit(samsung);
874 samsung->sabi = (samsung->f0000_segment + loca); 1088error_backlight:
875 1089 samsung_sysfs_exit(samsung);
876 if (debug) { 1090error_sysfs:
877 printk(KERN_DEBUG "This computer supports SABI==%x\n", 1091 samsung_sabi_exit(samsung);
878 loca + 0xf0000 - 6); 1092error_sabi:
879 printk(KERN_DEBUG "SABI header:\n"); 1093 samsung_platform_exit(samsung);
880 printk(KERN_DEBUG " SMI Port Number = 0x%04x\n", 1094error_platform:
881 readw(samsung->sabi +
882 config->header_offsets.port));
883 printk(KERN_DEBUG " SMI Interface Function = 0x%02x\n",
884 readb(samsung->sabi +
885 config->header_offsets.iface_func));
886 printk(KERN_DEBUG " SMI enable memory buffer = 0x%02x\n",
887 readb(samsung->sabi +
888 config->header_offsets.en_mem));
889 printk(KERN_DEBUG " SMI restore memory buffer = 0x%02x\n",
890 readb(samsung->sabi +
891 config->header_offsets.re_mem));
892 printk(KERN_DEBUG " SABI data offset = 0x%04x\n",
893 readw(samsung->sabi +
894 config->header_offsets.data_offset));
895 printk(KERN_DEBUG " SABI data segment = 0x%04x\n",
896 readw(samsung->sabi +
897 config->header_offsets.data_segment));
898 }
899
900 /* Get a pointer to the SABI Interface */
901 ifaceP = (readw(samsung->sabi + config->header_offsets.data_segment) & 0x0ffff) << 4;
902 ifaceP += readw(samsung->sabi + config->header_offsets.data_offset) & 0x0ffff;
903 samsung->sabi_iface = ioremap_nocache(ifaceP, 16);
904 if (!samsung->sabi_iface) {
905 pr_err("Can't remap %x\n", ifaceP);
906 goto error_no_signature;
907 }
908 if (debug) {
909 printk(KERN_DEBUG "ifaceP = 0x%08x\n", ifaceP);
910 printk(KERN_DEBUG "sabi_iface = %p\n", samsung->sabi_iface);
911
912 test_backlight();
913 test_wireless();
914
915 retval = sabi_get_command(commands->get_brightness,
916 &sretval);
917 printk(KERN_DEBUG "brightness = 0x%02x\n", sretval.retval[0]);
918 }
919
920 /* Turn on "Linux" mode in the BIOS */
921 if (commands->set_linux != 0xff) {
922 retval = sabi_set_command(commands->set_linux,
923 0x81);
924 if (retval) {
925 pr_warn("Linux mode was not set!\n");
926 goto error_no_platform;
927 }
928 }
929
930 /* Check for stepping quirk */
931 check_for_stepping_quirk();
932
933 /* knock up a platform device to hang stuff off of */
934 samsung->pdev = platform_device_register_simple("samsung", -1, NULL, 0);
935 if (IS_ERR(samsung->pdev))
936 goto error_no_platform;
937
938 /* create a backlight device to talk to this one */
939 memset(&props, 0, sizeof(struct backlight_properties));
940 props.type = BACKLIGHT_PLATFORM;
941 props.max_brightness = config->max_brightness -
942 config->min_brightness;
943 bd = backlight_device_register("samsung", &samsung->pdev->dev,
944 NULL, &backlight_ops,
945 &props);
946 if (IS_ERR(bd))
947 goto error_no_backlight;
948
949 samsung->backlight_device = bd;
950 samsung->backlight_device->props.brightness = read_brightness();
951 samsung->backlight_device->props.power = FB_BLANK_UNBLANK;
952 backlight_update_status(samsung->backlight_device);
953
954 retval = init_wireless(samsung->pdev);
955 if (retval)
956 goto error_no_rfk;
957
958 retval = device_create_file(&samsung->pdev->dev,
959 &dev_attr_performance_level);
960 if (retval)
961 goto error_file_create;
962
963 return 0;
964
965error_file_create:
966 destroy_wireless();
967
968error_no_rfk:
969 backlight_device_unregister(samsung->backlight_device);
970
971error_no_backlight:
972 platform_device_unregister(samsung->pdev);
973
974error_no_platform:
975 iounmap(samsung->sabi_iface);
976
977error_no_signature:
978 iounmap(samsung->f0000_segment);
979
980error_cant_map:
981 kfree(samsung); 1095 kfree(samsung);
982 samsung = NULL; 1096 return ret;
983 return -EINVAL;
984} 1097}
985 1098
986static void __exit samsung_exit(void) 1099static void __exit samsung_exit(void)
987{ 1100{
988 const struct sabi_commands *commands = &samsung->config->commands; 1101 struct samsung_laptop *samsung;
1102
1103 samsung = platform_get_drvdata(samsung_platform_device);
1104
1105 samsung_rfkill_exit(samsung);
1106 samsung_backlight_exit(samsung);
1107 samsung_sysfs_exit(samsung);
1108 samsung_sabi_exit(samsung);
1109 samsung_platform_exit(samsung);
989 1110
990 /* Turn off "Linux" mode in the BIOS */
991 if (commands->set_linux != 0xff)
992 sabi_set_command(commands->set_linux, 0x80);
993
994 device_remove_file(&samsung->pdev->dev, &dev_attr_performance_level);
995 backlight_device_unregister(samsung->backlight_device);
996 destroy_wireless();
997 iounmap(samsung->sabi_iface);
998 iounmap(samsung->f0000_segment);
999 platform_device_unregister(samsung->pdev);
1000 kfree(samsung); 1111 kfree(samsung);
1001 samsung = NULL; 1112 samsung_platform_device = NULL;
1002} 1113}
1003 1114
1004module_init(samsung_init); 1115module_init(samsung_init);