aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/toshiba_acpi.c
diff options
context:
space:
mode:
authorAkio Idehara <zbe64533@gmail.com>2012-04-05 12:46:43 -0400
committerMatthew Garrett <mjg@redhat.com>2012-05-31 14:26:39 -0400
commit121b7b0d2976c4b915434ae8005f0dde6e05e440 (patch)
treeb453eb6290586bcc6ef4fc717b98acebe6510fc6 /drivers/platform/x86/toshiba_acpi.c
parent62cce7526629e164513d3c67a06845953910f818 (diff)
toshiba_acpi: Add support for transflective LCD
Some Toshiba laptops have the transflective LCD and toshset can control its backlight state. I brought this feature to the mainline. To support transflective LCD, it's implemented by adding an extra level to the backlight and having 0 change to transflective mode. It was tested on a Toshiba Portege R500. Signed-off-by: Akio Idehara <zbe64533@gmail.com> Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers/platform/x86/toshiba_acpi.c')
-rw-r--r--drivers/platform/x86/toshiba_acpi.c61
1 files changed, 57 insertions, 4 deletions
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 1bb128bbcfc9..f88b9d22f39e 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -95,6 +95,7 @@ MODULE_LICENSE("GPL");
95 95
96/* registers */ 96/* registers */
97#define HCI_FAN 0x0004 97#define HCI_FAN 0x0004
98#define HCI_TR_BACKLIGHT 0x0005
98#define HCI_SYSTEM_EVENT 0x0016 99#define HCI_SYSTEM_EVENT 0x0016
99#define HCI_VIDEO_OUT 0x001c 100#define HCI_VIDEO_OUT 0x001c
100#define HCI_HOTKEY_EVENT 0x001e 101#define HCI_HOTKEY_EVENT 0x001e
@@ -134,6 +135,7 @@ struct toshiba_acpi_dev {
134 unsigned int system_event_supported:1; 135 unsigned int system_event_supported:1;
135 unsigned int ntfy_supported:1; 136 unsigned int ntfy_supported:1;
136 unsigned int info_supported:1; 137 unsigned int info_supported:1;
138 unsigned int tr_backlight_supported:1;
137 139
138 struct mutex mutex; 140 struct mutex mutex;
139}; 141};
@@ -478,16 +480,46 @@ static const struct rfkill_ops toshiba_rfk_ops = {
478 .poll = bt_rfkill_poll, 480 .poll = bt_rfkill_poll,
479}; 481};
480 482
483static int get_tr_backlight_status(struct toshiba_acpi_dev *dev, bool *enabled)
484{
485 u32 hci_result;
486 u32 status;
487
488 hci_read1(dev, HCI_TR_BACKLIGHT, &status, &hci_result);
489 *enabled = !status;
490 return hci_result == HCI_SUCCESS ? 0 : -EIO;
491}
492
493static int set_tr_backlight_status(struct toshiba_acpi_dev *dev, bool enable)
494{
495 u32 hci_result;
496 u32 value = !enable;
497
498 hci_write1(dev, HCI_TR_BACKLIGHT, value, &hci_result);
499 return hci_result == HCI_SUCCESS ? 0 : -EIO;
500}
501
481static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ; 502static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ;
482 503
483static int __get_lcd_brightness(struct toshiba_acpi_dev *dev) 504static int __get_lcd_brightness(struct toshiba_acpi_dev *dev)
484{ 505{
485 u32 hci_result; 506 u32 hci_result;
486 u32 value; 507 u32 value;
508 int brightness = 0;
509
510 if (dev->tr_backlight_supported) {
511 bool enabled;
512 int ret = get_tr_backlight_status(dev, &enabled);
513 if (ret)
514 return ret;
515 if (enabled)
516 return 0;
517 brightness++;
518 }
487 519
488 hci_read1(dev, HCI_LCD_BRIGHTNESS, &value, &hci_result); 520 hci_read1(dev, HCI_LCD_BRIGHTNESS, &value, &hci_result);
489 if (hci_result == HCI_SUCCESS) 521 if (hci_result == HCI_SUCCESS)
490 return (value >> HCI_LCD_BRIGHTNESS_SHIFT); 522 return brightness + (value >> HCI_LCD_BRIGHTNESS_SHIFT);
491 523
492 return -EIO; 524 return -EIO;
493} 525}
@@ -502,15 +534,16 @@ static int lcd_proc_show(struct seq_file *m, void *v)
502{ 534{
503 struct toshiba_acpi_dev *dev = m->private; 535 struct toshiba_acpi_dev *dev = m->private;
504 int value; 536 int value;
537 int levels;
505 538
506 if (!dev->backlight_dev) 539 if (!dev->backlight_dev)
507 return -ENODEV; 540 return -ENODEV;
508 541
542 levels = dev->backlight_dev->props.max_brightness + 1;
509 value = get_lcd_brightness(dev->backlight_dev); 543 value = get_lcd_brightness(dev->backlight_dev);
510 if (value >= 0) { 544 if (value >= 0) {
511 seq_printf(m, "brightness: %d\n", value); 545 seq_printf(m, "brightness: %d\n", value);
512 seq_printf(m, "brightness_levels: %d\n", 546 seq_printf(m, "brightness_levels: %d\n", levels);
513 HCI_LCD_BRIGHTNESS_LEVELS);
514 return 0; 547 return 0;
515 } 548 }
516 549
@@ -527,6 +560,15 @@ static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value)
527{ 560{
528 u32 hci_result; 561 u32 hci_result;
529 562
563 if (dev->tr_backlight_supported) {
564 bool enable = !value;
565 int ret = set_tr_backlight_status(dev, enable);
566 if (ret)
567 return ret;
568 if (value)
569 value--;
570 }
571
530 value = value << HCI_LCD_BRIGHTNESS_SHIFT; 572 value = value << HCI_LCD_BRIGHTNESS_SHIFT;
531 hci_write1(dev, HCI_LCD_BRIGHTNESS, value, &hci_result); 573 hci_write1(dev, HCI_LCD_BRIGHTNESS, value, &hci_result);
532 return hci_result == HCI_SUCCESS ? 0 : -EIO; 574 return hci_result == HCI_SUCCESS ? 0 : -EIO;
@@ -546,6 +588,7 @@ static ssize_t lcd_proc_write(struct file *file, const char __user *buf,
546 size_t len; 588 size_t len;
547 int value; 589 int value;
548 int ret; 590 int ret;
591 int levels = dev->backlight_dev->props.max_brightness + 1;
549 592
550 len = min(count, sizeof(cmd) - 1); 593 len = min(count, sizeof(cmd) - 1);
551 if (copy_from_user(cmd, buf, len)) 594 if (copy_from_user(cmd, buf, len))
@@ -553,7 +596,7 @@ static ssize_t lcd_proc_write(struct file *file, const char __user *buf,
553 cmd[len] = '\0'; 596 cmd[len] = '\0';
554 597
555 if (sscanf(cmd, " brightness : %i", &value) == 1 && 598 if (sscanf(cmd, " brightness : %i", &value) == 1 &&
556 value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) { 599 value >= 0 && value < levels) {
557 ret = set_lcd_brightness(dev, value); 600 ret = set_lcd_brightness(dev, value);
558 if (ret == 0) 601 if (ret == 0)
559 ret = count; 602 ret = count;
@@ -865,6 +908,7 @@ static void remove_toshiba_proc_entries(struct toshiba_acpi_dev *dev)
865} 908}
866 909
867static const struct backlight_ops toshiba_backlight_data = { 910static const struct backlight_ops toshiba_backlight_data = {
911 .options = BL_CORE_SUSPENDRESUME,
868 .get_brightness = get_lcd_brightness, 912 .get_brightness = get_lcd_brightness,
869 .update_status = set_lcd_status, 913 .update_status = set_lcd_status,
870}; 914};
@@ -1030,6 +1074,7 @@ static int __devinit toshiba_acpi_setup_backlight(struct toshiba_acpi_dev *dev)
1030 struct backlight_properties props; 1074 struct backlight_properties props;
1031 int brightness; 1075 int brightness;
1032 int ret; 1076 int ret;
1077 bool enabled;
1033 1078
1034 /* 1079 /*
1035 * Some machines don't support the backlight methods at all, and 1080 * Some machines don't support the backlight methods at all, and
@@ -1046,10 +1091,18 @@ static int __devinit toshiba_acpi_setup_backlight(struct toshiba_acpi_dev *dev)
1046 return 0; 1091 return 0;
1047 } 1092 }
1048 1093
1094 /* Determine whether or not BIOS supports transflective backlight */
1095 ret = get_tr_backlight_status(dev, &enabled);
1096 dev->tr_backlight_supported = !ret;
1097
1049 props.type = BACKLIGHT_PLATFORM; 1098 props.type = BACKLIGHT_PLATFORM;
1050 props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; 1099 props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
1051 memset(&props, 0, sizeof(props)); 1100 memset(&props, 0, sizeof(props));
1052 1101
1102 /* adding an extra level and having 0 change to transflective mode */
1103 if (dev->tr_backlight_supported)
1104 props.max_brightness++;
1105
1053 dev->backlight_dev = backlight_device_register("toshiba", 1106 dev->backlight_dev = backlight_device_register("toshiba",
1054 &dev->acpi_dev->dev, 1107 &dev->acpi_dev->dev,
1055 dev, 1108 dev,