diff options
Diffstat (limited to 'drivers/acpi/video.c')
-rw-r--r-- | drivers/acpi/video.c | 241 |
1 files changed, 176 insertions, 65 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 6e99eea689c8..e0b97add8c63 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2004 Luming Yu <luming.yu@intel.com> | 4 | * Copyright (C) 2004 Luming Yu <luming.yu@intel.com> |
5 | * Copyright (C) 2004 Bruno Ducrot <ducrot@poupinou.org> | 5 | * Copyright (C) 2004 Bruno Ducrot <ducrot@poupinou.org> |
6 | * Copyright (C) 2006 Thomas Tuttle <linux-kernel@ttuttle.net> | ||
6 | * | 7 | * |
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 8 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
8 | * | 9 | * |
@@ -31,6 +32,7 @@ | |||
31 | #include <linux/proc_fs.h> | 32 | #include <linux/proc_fs.h> |
32 | #include <linux/seq_file.h> | 33 | #include <linux/seq_file.h> |
33 | 34 | ||
35 | #include <linux/backlight.h> | ||
34 | #include <asm/uaccess.h> | 36 | #include <asm/uaccess.h> |
35 | 37 | ||
36 | #include <acpi/acpi_bus.h> | 38 | #include <acpi/acpi_bus.h> |
@@ -47,14 +49,20 @@ | |||
47 | #define ACPI_VIDEO_NOTIFY_NEXT_OUTPUT 0x83 | 49 | #define ACPI_VIDEO_NOTIFY_NEXT_OUTPUT 0x83 |
48 | #define ACPI_VIDEO_NOTIFY_PREV_OUTPUT 0x84 | 50 | #define ACPI_VIDEO_NOTIFY_PREV_OUTPUT 0x84 |
49 | 51 | ||
50 | #define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS 0x82 | 52 | #define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS 0x85 |
51 | #define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS 0x83 | 53 | #define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS 0x86 |
52 | #define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x84 | 54 | #define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87 |
53 | #define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x85 | 55 | #define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x88 |
54 | #define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x86 | 56 | #define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x89 |
55 | 57 | ||
56 | #define ACPI_VIDEO_HEAD_INVALID (~0u - 1) | 58 | #define ACPI_VIDEO_HEAD_INVALID (~0u - 1) |
57 | #define ACPI_VIDEO_HEAD_END (~0u) | 59 | #define ACPI_VIDEO_HEAD_END (~0u) |
60 | #define MAX_NAME_LEN 20 | ||
61 | |||
62 | #define ACPI_VIDEO_DISPLAY_CRT 1 | ||
63 | #define ACPI_VIDEO_DISPLAY_TV 2 | ||
64 | #define ACPI_VIDEO_DISPLAY_DVI 3 | ||
65 | #define ACPI_VIDEO_DISPLAY_LCD 4 | ||
58 | 66 | ||
59 | #define _COMPONENT ACPI_VIDEO_COMPONENT | 67 | #define _COMPONENT ACPI_VIDEO_COMPONENT |
60 | ACPI_MODULE_NAME("acpi_video") | 68 | ACPI_MODULE_NAME("acpi_video") |
@@ -130,20 +138,21 @@ struct acpi_video_device_flags { | |||
130 | u8 crt:1; | 138 | u8 crt:1; |
131 | u8 lcd:1; | 139 | u8 lcd:1; |
132 | u8 tvout:1; | 140 | u8 tvout:1; |
141 | u8 dvi:1; | ||
133 | u8 bios:1; | 142 | u8 bios:1; |
134 | u8 unknown:1; | 143 | u8 unknown:1; |
135 | u8 reserved:3; | 144 | u8 reserved:2; |
136 | }; | 145 | }; |
137 | 146 | ||
138 | struct acpi_video_device_cap { | 147 | struct acpi_video_device_cap { |
139 | u8 _ADR:1; /*Return the unique ID */ | 148 | u8 _ADR:1; /*Return the unique ID */ |
140 | u8 _BCL:1; /*Query list of brightness control levels supported */ | 149 | u8 _BCL:1; /*Query list of brightness control levels supported */ |
141 | u8 _BCM:1; /*Set the brightness level */ | 150 | u8 _BCM:1; /*Set the brightness level */ |
151 | u8 _BQC:1; /* Get current brightness level */ | ||
142 | u8 _DDC:1; /*Return the EDID for this device */ | 152 | u8 _DDC:1; /*Return the EDID for this device */ |
143 | u8 _DCS:1; /*Return status of output device */ | 153 | u8 _DCS:1; /*Return status of output device */ |
144 | u8 _DGS:1; /*Query graphics state */ | 154 | u8 _DGS:1; /*Query graphics state */ |
145 | u8 _DSS:1; /*Device state set */ | 155 | u8 _DSS:1; /*Device state set */ |
146 | u8 _reserved:1; | ||
147 | }; | 156 | }; |
148 | 157 | ||
149 | struct acpi_video_device_brightness { | 158 | struct acpi_video_device_brightness { |
@@ -160,6 +169,8 @@ struct acpi_video_device { | |||
160 | struct acpi_video_bus *video; | 169 | struct acpi_video_bus *video; |
161 | struct acpi_device *dev; | 170 | struct acpi_device *dev; |
162 | struct acpi_video_device_brightness *brightness; | 171 | struct acpi_video_device_brightness *brightness; |
172 | struct backlight_device *backlight; | ||
173 | struct backlight_properties *data; | ||
163 | }; | 174 | }; |
164 | 175 | ||
165 | /* bus */ | 176 | /* bus */ |
@@ -254,11 +265,35 @@ static void acpi_video_device_bind(struct acpi_video_bus *video, | |||
254 | struct acpi_video_device *device); | 265 | struct acpi_video_device *device); |
255 | static int acpi_video_device_enumerate(struct acpi_video_bus *video); | 266 | static int acpi_video_device_enumerate(struct acpi_video_bus *video); |
256 | static int acpi_video_switch_output(struct acpi_video_bus *video, int event); | 267 | static int acpi_video_switch_output(struct acpi_video_bus *video, int event); |
268 | static int acpi_video_device_lcd_set_level(struct acpi_video_device *device, | ||
269 | int level); | ||
270 | static int acpi_video_device_lcd_get_level_current( | ||
271 | struct acpi_video_device *device, | ||
272 | unsigned long *level); | ||
257 | static int acpi_video_get_next_level(struct acpi_video_device *device, | 273 | static int acpi_video_get_next_level(struct acpi_video_device *device, |
258 | u32 level_current, u32 event); | 274 | u32 level_current, u32 event); |
259 | static void acpi_video_switch_brightness(struct acpi_video_device *device, | 275 | static void acpi_video_switch_brightness(struct acpi_video_device *device, |
260 | int event); | 276 | int event); |
261 | 277 | ||
278 | /*backlight device sysfs support*/ | ||
279 | static int acpi_video_get_brightness(struct backlight_device *bd) | ||
280 | { | ||
281 | unsigned long cur_level; | ||
282 | struct acpi_video_device *vd = | ||
283 | (struct acpi_video_device *)class_get_devdata(&bd->class_dev); | ||
284 | acpi_video_device_lcd_get_level_current(vd, &cur_level); | ||
285 | return (int) cur_level; | ||
286 | } | ||
287 | |||
288 | static int acpi_video_set_brightness(struct backlight_device *bd) | ||
289 | { | ||
290 | int request_level = bd->props->brightness; | ||
291 | struct acpi_video_device *vd = | ||
292 | (struct acpi_video_device *)class_get_devdata(&bd->class_dev); | ||
293 | acpi_video_device_lcd_set_level(vd, request_level); | ||
294 | return 0; | ||
295 | } | ||
296 | |||
262 | /* -------------------------------------------------------------------------- | 297 | /* -------------------------------------------------------------------------- |
263 | Video Management | 298 | Video Management |
264 | -------------------------------------------------------------------------- */ | 299 | -------------------------------------------------------------------------- */ |
@@ -384,7 +419,7 @@ acpi_video_device_EDID(struct acpi_video_device *device, | |||
384 | if (ACPI_FAILURE(status)) | 419 | if (ACPI_FAILURE(status)) |
385 | return -ENODEV; | 420 | return -ENODEV; |
386 | 421 | ||
387 | obj = (union acpi_object *)buffer.pointer; | 422 | obj = buffer.pointer; |
388 | 423 | ||
389 | if (obj && obj->type == ACPI_TYPE_BUFFER) | 424 | if (obj && obj->type == ACPI_TYPE_BUFFER) |
390 | *edid = obj; | 425 | *edid = obj; |
@@ -496,6 +531,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
496 | acpi_integer status; | 531 | acpi_integer status; |
497 | acpi_handle h_dummy1; | 532 | acpi_handle h_dummy1; |
498 | int i; | 533 | int i; |
534 | u32 max_level = 0; | ||
499 | union acpi_object *obj = NULL; | 535 | union acpi_object *obj = NULL; |
500 | struct acpi_video_device_brightness *br = NULL; | 536 | struct acpi_video_device_brightness *br = NULL; |
501 | 537 | ||
@@ -511,6 +547,8 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
511 | if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCM", &h_dummy1))) { | 547 | if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCM", &h_dummy1))) { |
512 | device->cap._BCM = 1; | 548 | device->cap._BCM = 1; |
513 | } | 549 | } |
550 | if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle,"_BQC",&h_dummy1))) | ||
551 | device->cap._BQC = 1; | ||
514 | if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) { | 552 | if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) { |
515 | device->cap._DDC = 1; | 553 | device->cap._DDC = 1; |
516 | } | 554 | } |
@@ -530,11 +568,10 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
530 | int count = 0; | 568 | int count = 0; |
531 | union acpi_object *o; | 569 | union acpi_object *o; |
532 | 570 | ||
533 | br = kmalloc(sizeof(*br), GFP_KERNEL); | 571 | br = kzalloc(sizeof(*br), GFP_KERNEL); |
534 | if (!br) { | 572 | if (!br) { |
535 | printk(KERN_ERR "can't allocate memory\n"); | 573 | printk(KERN_ERR "can't allocate memory\n"); |
536 | } else { | 574 | } else { |
537 | memset(br, 0, sizeof(*br)); | ||
538 | br->levels = kmalloc(obj->package.count * | 575 | br->levels = kmalloc(obj->package.count * |
539 | sizeof *(br->levels), GFP_KERNEL); | 576 | sizeof *(br->levels), GFP_KERNEL); |
540 | if (!br->levels) | 577 | if (!br->levels) |
@@ -548,6 +585,8 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
548 | continue; | 585 | continue; |
549 | } | 586 | } |
550 | br->levels[count] = (u32) o->integer.value; | 587 | br->levels[count] = (u32) o->integer.value; |
588 | if (br->levels[count] > max_level) | ||
589 | max_level = br->levels[count]; | ||
551 | count++; | 590 | count++; |
552 | } | 591 | } |
553 | out: | 592 | out: |
@@ -566,6 +605,37 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
566 | 605 | ||
567 | kfree(obj); | 606 | kfree(obj); |
568 | 607 | ||
608 | if (device->cap._BCL && device->cap._BCM && device->cap._BQC){ | ||
609 | unsigned long tmp; | ||
610 | static int count = 0; | ||
611 | char *name; | ||
612 | struct backlight_properties *acpi_video_data; | ||
613 | |||
614 | name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); | ||
615 | if (!name) | ||
616 | return; | ||
617 | |||
618 | acpi_video_data = kzalloc( | ||
619 | sizeof(struct backlight_properties), | ||
620 | GFP_KERNEL); | ||
621 | if (!acpi_video_data){ | ||
622 | kfree(name); | ||
623 | return; | ||
624 | } | ||
625 | acpi_video_data->owner = THIS_MODULE; | ||
626 | acpi_video_data->get_brightness = | ||
627 | acpi_video_get_brightness; | ||
628 | acpi_video_data->update_status = | ||
629 | acpi_video_set_brightness; | ||
630 | sprintf(name, "acpi_video%d", count++); | ||
631 | device->data = acpi_video_data; | ||
632 | acpi_video_data->max_brightness = max_level; | ||
633 | acpi_video_device_lcd_get_level_current(device, &tmp); | ||
634 | acpi_video_data->brightness = (int)tmp; | ||
635 | device->backlight = backlight_device_register(name, | ||
636 | NULL, device, acpi_video_data); | ||
637 | kfree(name); | ||
638 | } | ||
569 | return; | 639 | return; |
570 | } | 640 | } |
571 | 641 | ||
@@ -652,8 +722,7 @@ static struct proc_dir_entry *acpi_video_dir; | |||
652 | 722 | ||
653 | static int acpi_video_device_info_seq_show(struct seq_file *seq, void *offset) | 723 | static int acpi_video_device_info_seq_show(struct seq_file *seq, void *offset) |
654 | { | 724 | { |
655 | struct acpi_video_device *dev = | 725 | struct acpi_video_device *dev = seq->private; |
656 | (struct acpi_video_device *)seq->private; | ||
657 | 726 | ||
658 | 727 | ||
659 | if (!dev) | 728 | if (!dev) |
@@ -667,6 +736,8 @@ static int acpi_video_device_info_seq_show(struct seq_file *seq, void *offset) | |||
667 | seq_printf(seq, "LCD\n"); | 736 | seq_printf(seq, "LCD\n"); |
668 | else if (dev->flags.tvout) | 737 | else if (dev->flags.tvout) |
669 | seq_printf(seq, "TVOUT\n"); | 738 | seq_printf(seq, "TVOUT\n"); |
739 | else if (dev->flags.dvi) | ||
740 | seq_printf(seq, "DVI\n"); | ||
670 | else | 741 | else |
671 | seq_printf(seq, "UNKNOWN\n"); | 742 | seq_printf(seq, "UNKNOWN\n"); |
672 | 743 | ||
@@ -686,8 +757,7 @@ acpi_video_device_info_open_fs(struct inode *inode, struct file *file) | |||
686 | static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset) | 757 | static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset) |
687 | { | 758 | { |
688 | int status; | 759 | int status; |
689 | struct acpi_video_device *dev = | 760 | struct acpi_video_device *dev = seq->private; |
690 | (struct acpi_video_device *)seq->private; | ||
691 | unsigned long state; | 761 | unsigned long state; |
692 | 762 | ||
693 | 763 | ||
@@ -725,8 +795,8 @@ acpi_video_device_write_state(struct file *file, | |||
725 | size_t count, loff_t * data) | 795 | size_t count, loff_t * data) |
726 | { | 796 | { |
727 | int status; | 797 | int status; |
728 | struct seq_file *m = (struct seq_file *)file->private_data; | 798 | struct seq_file *m = file->private_data; |
729 | struct acpi_video_device *dev = (struct acpi_video_device *)m->private; | 799 | struct acpi_video_device *dev = m->private; |
730 | char str[12] = { 0 }; | 800 | char str[12] = { 0 }; |
731 | u32 state = 0; | 801 | u32 state = 0; |
732 | 802 | ||
@@ -752,8 +822,7 @@ acpi_video_device_write_state(struct file *file, | |||
752 | static int | 822 | static int |
753 | acpi_video_device_brightness_seq_show(struct seq_file *seq, void *offset) | 823 | acpi_video_device_brightness_seq_show(struct seq_file *seq, void *offset) |
754 | { | 824 | { |
755 | struct acpi_video_device *dev = | 825 | struct acpi_video_device *dev = seq->private; |
756 | (struct acpi_video_device *)seq->private; | ||
757 | int i; | 826 | int i; |
758 | 827 | ||
759 | 828 | ||
@@ -782,8 +851,8 @@ acpi_video_device_write_brightness(struct file *file, | |||
782 | const char __user * buffer, | 851 | const char __user * buffer, |
783 | size_t count, loff_t * data) | 852 | size_t count, loff_t * data) |
784 | { | 853 | { |
785 | struct seq_file *m = (struct seq_file *)file->private_data; | 854 | struct seq_file *m = file->private_data; |
786 | struct acpi_video_device *dev = (struct acpi_video_device *)m->private; | 855 | struct acpi_video_device *dev = m->private; |
787 | char str[4] = { 0 }; | 856 | char str[4] = { 0 }; |
788 | unsigned int level = 0; | 857 | unsigned int level = 0; |
789 | int i; | 858 | int i; |
@@ -815,8 +884,7 @@ acpi_video_device_write_brightness(struct file *file, | |||
815 | 884 | ||
816 | static int acpi_video_device_EDID_seq_show(struct seq_file *seq, void *offset) | 885 | static int acpi_video_device_EDID_seq_show(struct seq_file *seq, void *offset) |
817 | { | 886 | { |
818 | struct acpi_video_device *dev = | 887 | struct acpi_video_device *dev = seq->private; |
819 | (struct acpi_video_device *)seq->private; | ||
820 | int status; | 888 | int status; |
821 | int i; | 889 | int i; |
822 | union acpi_object *edid = NULL; | 890 | union acpi_object *edid = NULL; |
@@ -864,7 +932,7 @@ static int acpi_video_device_add_fs(struct acpi_device *device) | |||
864 | if (!device) | 932 | if (!device) |
865 | return -ENODEV; | 933 | return -ENODEV; |
866 | 934 | ||
867 | vid_dev = (struct acpi_video_device *)acpi_driver_data(device); | 935 | vid_dev = acpi_driver_data(device); |
868 | if (!vid_dev) | 936 | if (!vid_dev) |
869 | return -ENODEV; | 937 | return -ENODEV; |
870 | 938 | ||
@@ -929,7 +997,7 @@ static int acpi_video_device_remove_fs(struct acpi_device *device) | |||
929 | { | 997 | { |
930 | struct acpi_video_device *vid_dev; | 998 | struct acpi_video_device *vid_dev; |
931 | 999 | ||
932 | vid_dev = (struct acpi_video_device *)acpi_driver_data(device); | 1000 | vid_dev = acpi_driver_data(device); |
933 | if (!vid_dev || !vid_dev->video || !vid_dev->video->dir) | 1001 | if (!vid_dev || !vid_dev->video || !vid_dev->video->dir) |
934 | return -ENODEV; | 1002 | return -ENODEV; |
935 | 1003 | ||
@@ -948,7 +1016,7 @@ static int acpi_video_device_remove_fs(struct acpi_device *device) | |||
948 | /* video bus */ | 1016 | /* video bus */ |
949 | static int acpi_video_bus_info_seq_show(struct seq_file *seq, void *offset) | 1017 | static int acpi_video_bus_info_seq_show(struct seq_file *seq, void *offset) |
950 | { | 1018 | { |
951 | struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private; | 1019 | struct acpi_video_bus *video = seq->private; |
952 | 1020 | ||
953 | 1021 | ||
954 | if (!video) | 1022 | if (!video) |
@@ -973,7 +1041,7 @@ static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file) | |||
973 | 1041 | ||
974 | static int acpi_video_bus_ROM_seq_show(struct seq_file *seq, void *offset) | 1042 | static int acpi_video_bus_ROM_seq_show(struct seq_file *seq, void *offset) |
975 | { | 1043 | { |
976 | struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private; | 1044 | struct acpi_video_bus *video = seq->private; |
977 | 1045 | ||
978 | 1046 | ||
979 | if (!video) | 1047 | if (!video) |
@@ -993,7 +1061,7 @@ static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file) | |||
993 | 1061 | ||
994 | static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset) | 1062 | static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset) |
995 | { | 1063 | { |
996 | struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private; | 1064 | struct acpi_video_bus *video = seq->private; |
997 | unsigned long options; | 1065 | unsigned long options; |
998 | int status; | 1066 | int status; |
999 | 1067 | ||
@@ -1031,7 +1099,7 @@ acpi_video_bus_POST_info_open_fs(struct inode *inode, struct file *file) | |||
1031 | 1099 | ||
1032 | static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset) | 1100 | static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset) |
1033 | { | 1101 | { |
1034 | struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private; | 1102 | struct acpi_video_bus *video = seq->private; |
1035 | int status; | 1103 | int status; |
1036 | unsigned long id; | 1104 | unsigned long id; |
1037 | 1105 | ||
@@ -1052,7 +1120,7 @@ static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset) | |||
1052 | 1120 | ||
1053 | static int acpi_video_bus_DOS_seq_show(struct seq_file *seq, void *offset) | 1121 | static int acpi_video_bus_DOS_seq_show(struct seq_file *seq, void *offset) |
1054 | { | 1122 | { |
1055 | struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private; | 1123 | struct acpi_video_bus *video = seq->private; |
1056 | 1124 | ||
1057 | 1125 | ||
1058 | seq_printf(seq, "DOS setting: <%d>\n", video->dos_setting); | 1126 | seq_printf(seq, "DOS setting: <%d>\n", video->dos_setting); |
@@ -1077,8 +1145,8 @@ acpi_video_bus_write_POST(struct file *file, | |||
1077 | size_t count, loff_t * data) | 1145 | size_t count, loff_t * data) |
1078 | { | 1146 | { |
1079 | int status; | 1147 | int status; |
1080 | struct seq_file *m = (struct seq_file *)file->private_data; | 1148 | struct seq_file *m = file->private_data; |
1081 | struct acpi_video_bus *video = (struct acpi_video_bus *)m->private; | 1149 | struct acpi_video_bus *video = m->private; |
1082 | char str[12] = { 0 }; | 1150 | char str[12] = { 0 }; |
1083 | unsigned long opt, options; | 1151 | unsigned long opt, options; |
1084 | 1152 | ||
@@ -1117,8 +1185,8 @@ acpi_video_bus_write_DOS(struct file *file, | |||
1117 | size_t count, loff_t * data) | 1185 | size_t count, loff_t * data) |
1118 | { | 1186 | { |
1119 | int status; | 1187 | int status; |
1120 | struct seq_file *m = (struct seq_file *)file->private_data; | 1188 | struct seq_file *m = file->private_data; |
1121 | struct acpi_video_bus *video = (struct acpi_video_bus *)m->private; | 1189 | struct acpi_video_bus *video = m->private; |
1122 | char str[12] = { 0 }; | 1190 | char str[12] = { 0 }; |
1123 | unsigned long opt; | 1191 | unsigned long opt; |
1124 | 1192 | ||
@@ -1148,7 +1216,7 @@ static int acpi_video_bus_add_fs(struct acpi_device *device) | |||
1148 | struct acpi_video_bus *video; | 1216 | struct acpi_video_bus *video; |
1149 | 1217 | ||
1150 | 1218 | ||
1151 | video = (struct acpi_video_bus *)acpi_driver_data(device); | 1219 | video = acpi_driver_data(device); |
1152 | 1220 | ||
1153 | if (!acpi_device_dir(device)) { | 1221 | if (!acpi_device_dir(device)) { |
1154 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), | 1222 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), |
@@ -1224,7 +1292,7 @@ static int acpi_video_bus_remove_fs(struct acpi_device *device) | |||
1224 | struct acpi_video_bus *video; | 1292 | struct acpi_video_bus *video; |
1225 | 1293 | ||
1226 | 1294 | ||
1227 | video = (struct acpi_video_bus *)acpi_driver_data(device); | 1295 | video = acpi_driver_data(device); |
1228 | 1296 | ||
1229 | if (acpi_device_dir(device)) { | 1297 | if (acpi_device_dir(device)) { |
1230 | remove_proc_entry("info", acpi_device_dir(device)); | 1298 | remove_proc_entry("info", acpi_device_dir(device)); |
@@ -1244,6 +1312,16 @@ static int acpi_video_bus_remove_fs(struct acpi_device *device) | |||
1244 | -------------------------------------------------------------------------- */ | 1312 | -------------------------------------------------------------------------- */ |
1245 | 1313 | ||
1246 | /* device interface */ | 1314 | /* device interface */ |
1315 | static struct acpi_video_device_attrib* | ||
1316 | acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id) | ||
1317 | { | ||
1318 | int count; | ||
1319 | |||
1320 | for(count = 0; count < video->attached_count; count++) | ||
1321 | if((video->attached_array[count].value.int_val & 0xffff) == device_id) | ||
1322 | return &(video->attached_array[count].value.attrib); | ||
1323 | return NULL; | ||
1324 | } | ||
1247 | 1325 | ||
1248 | static int | 1326 | static int |
1249 | acpi_video_bus_get_one_device(struct acpi_device *device, | 1327 | acpi_video_bus_get_one_device(struct acpi_device *device, |
@@ -1252,7 +1330,7 @@ acpi_video_bus_get_one_device(struct acpi_device *device, | |||
1252 | unsigned long device_id; | 1330 | unsigned long device_id; |
1253 | int status; | 1331 | int status; |
1254 | struct acpi_video_device *data; | 1332 | struct acpi_video_device *data; |
1255 | 1333 | struct acpi_video_device_attrib* attribute; | |
1256 | 1334 | ||
1257 | if (!device || !video) | 1335 | if (!device || !video) |
1258 | return -EINVAL; | 1336 | return -EINVAL; |
@@ -1261,12 +1339,10 @@ acpi_video_bus_get_one_device(struct acpi_device *device, | |||
1261 | acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id); | 1339 | acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id); |
1262 | if (ACPI_SUCCESS(status)) { | 1340 | if (ACPI_SUCCESS(status)) { |
1263 | 1341 | ||
1264 | data = kmalloc(sizeof(struct acpi_video_device), GFP_KERNEL); | 1342 | data = kzalloc(sizeof(struct acpi_video_device), GFP_KERNEL); |
1265 | if (!data) | 1343 | if (!data) |
1266 | return -ENOMEM; | 1344 | return -ENOMEM; |
1267 | 1345 | ||
1268 | memset(data, 0, sizeof(struct acpi_video_device)); | ||
1269 | |||
1270 | strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME); | 1346 | strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME); |
1271 | strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS); | 1347 | strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS); |
1272 | acpi_driver_data(device) = data; | 1348 | acpi_driver_data(device) = data; |
@@ -1275,20 +1351,30 @@ acpi_video_bus_get_one_device(struct acpi_device *device, | |||
1275 | data->video = video; | 1351 | data->video = video; |
1276 | data->dev = device; | 1352 | data->dev = device; |
1277 | 1353 | ||
1278 | switch (device_id & 0xffff) { | 1354 | attribute = acpi_video_get_device_attr(video, device_id); |
1279 | case 0x0100: | 1355 | |
1280 | data->flags.crt = 1; | 1356 | if((attribute != NULL) && attribute->device_id_scheme) { |
1281 | break; | 1357 | switch (attribute->display_type) { |
1282 | case 0x0400: | 1358 | case ACPI_VIDEO_DISPLAY_CRT: |
1283 | data->flags.lcd = 1; | 1359 | data->flags.crt = 1; |
1284 | break; | 1360 | break; |
1285 | case 0x0200: | 1361 | case ACPI_VIDEO_DISPLAY_TV: |
1286 | data->flags.tvout = 1; | 1362 | data->flags.tvout = 1; |
1287 | break; | 1363 | break; |
1288 | default: | 1364 | case ACPI_VIDEO_DISPLAY_DVI: |
1365 | data->flags.dvi = 1; | ||
1366 | break; | ||
1367 | case ACPI_VIDEO_DISPLAY_LCD: | ||
1368 | data->flags.lcd = 1; | ||
1369 | break; | ||
1370 | default: | ||
1371 | data->flags.unknown = 1; | ||
1372 | break; | ||
1373 | } | ||
1374 | if(attribute->bios_can_detect) | ||
1375 | data->flags.bios = 1; | ||
1376 | } else | ||
1289 | data->flags.unknown = 1; | 1377 | data->flags.unknown = 1; |
1290 | break; | ||
1291 | } | ||
1292 | 1378 | ||
1293 | acpi_video_device_bind(video, data); | 1379 | acpi_video_device_bind(video, data); |
1294 | acpi_video_device_find_cap(data); | 1380 | acpi_video_device_find_cap(data); |
@@ -1401,7 +1487,7 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) | |||
1401 | return status; | 1487 | return status; |
1402 | } | 1488 | } |
1403 | 1489 | ||
1404 | dod = (union acpi_object *)buffer.pointer; | 1490 | dod = buffer.pointer; |
1405 | if (!dod || (dod->type != ACPI_TYPE_PACKAGE)) { | 1491 | if (!dod || (dod->type != ACPI_TYPE_PACKAGE)) { |
1406 | ACPI_EXCEPTION((AE_INFO, status, "Invalid _DOD data")); | 1492 | ACPI_EXCEPTION((AE_INFO, status, "Invalid _DOD data")); |
1407 | status = -EFAULT; | 1493 | status = -EFAULT; |
@@ -1424,7 +1510,7 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) | |||
1424 | 1510 | ||
1425 | count = 0; | 1511 | count = 0; |
1426 | for (i = 0; i < dod->package.count; i++) { | 1512 | for (i = 0; i < dod->package.count; i++) { |
1427 | obj = (union acpi_object *)&dod->package.elements[i]; | 1513 | obj = &dod->package.elements[i]; |
1428 | 1514 | ||
1429 | if (obj->type != ACPI_TYPE_INTEGER) { | 1515 | if (obj->type != ACPI_TYPE_INTEGER) { |
1430 | printk(KERN_ERR PREFIX "Invalid _DOD data\n"); | 1516 | printk(KERN_ERR PREFIX "Invalid _DOD data\n"); |
@@ -1507,8 +1593,34 @@ static int | |||
1507 | acpi_video_get_next_level(struct acpi_video_device *device, | 1593 | acpi_video_get_next_level(struct acpi_video_device *device, |
1508 | u32 level_current, u32 event) | 1594 | u32 level_current, u32 event) |
1509 | { | 1595 | { |
1510 | /*Fix me */ | 1596 | int min, max, min_above, max_below, i, l; |
1511 | return level_current; | 1597 | max = max_below = 0; |
1598 | min = min_above = 255; | ||
1599 | for (i = 0; i < device->brightness->count; i++) { | ||
1600 | l = device->brightness->levels[i]; | ||
1601 | if (l < min) | ||
1602 | min = l; | ||
1603 | if (l > max) | ||
1604 | max = l; | ||
1605 | if (l < min_above && l > level_current) | ||
1606 | min_above = l; | ||
1607 | if (l > max_below && l < level_current) | ||
1608 | max_below = l; | ||
1609 | } | ||
1610 | |||
1611 | switch (event) { | ||
1612 | case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: | ||
1613 | return (level_current < max) ? min_above : min; | ||
1614 | case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: | ||
1615 | return (level_current < max) ? min_above : max; | ||
1616 | case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: | ||
1617 | return (level_current > min) ? max_below : min; | ||
1618 | case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: | ||
1619 | case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: | ||
1620 | return 0; | ||
1621 | default: | ||
1622 | return level_current; | ||
1623 | } | ||
1512 | } | 1624 | } |
1513 | 1625 | ||
1514 | static void | 1626 | static void |
@@ -1566,7 +1678,10 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) | |||
1566 | status = acpi_remove_notify_handler(device->dev->handle, | 1678 | status = acpi_remove_notify_handler(device->dev->handle, |
1567 | ACPI_DEVICE_NOTIFY, | 1679 | ACPI_DEVICE_NOTIFY, |
1568 | acpi_video_device_notify); | 1680 | acpi_video_device_notify); |
1569 | 1681 | if (device->backlight){ | |
1682 | backlight_device_unregister(device->backlight); | ||
1683 | kfree(device->data); | ||
1684 | } | ||
1570 | return 0; | 1685 | return 0; |
1571 | } | 1686 | } |
1572 | 1687 | ||
@@ -1610,7 +1725,7 @@ static int acpi_video_bus_stop_devices(struct acpi_video_bus *video) | |||
1610 | 1725 | ||
1611 | static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) | 1726 | static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) |
1612 | { | 1727 | { |
1613 | struct acpi_video_bus *video = (struct acpi_video_bus *)data; | 1728 | struct acpi_video_bus *video = data; |
1614 | struct acpi_device *device = NULL; | 1729 | struct acpi_device *device = NULL; |
1615 | 1730 | ||
1616 | printk("video bus notify\n"); | 1731 | printk("video bus notify\n"); |
@@ -1652,12 +1767,9 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) | |||
1652 | 1767 | ||
1653 | static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) | 1768 | static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) |
1654 | { | 1769 | { |
1655 | struct acpi_video_device *video_device = | 1770 | struct acpi_video_device *video_device = data; |
1656 | (struct acpi_video_device *)data; | ||
1657 | struct acpi_device *device = NULL; | 1771 | struct acpi_device *device = NULL; |
1658 | 1772 | ||
1659 | |||
1660 | printk("video device notify\n"); | ||
1661 | if (!video_device) | 1773 | if (!video_device) |
1662 | return; | 1774 | return; |
1663 | 1775 | ||
@@ -1694,10 +1806,9 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
1694 | if (!device) | 1806 | if (!device) |
1695 | return -EINVAL; | 1807 | return -EINVAL; |
1696 | 1808 | ||
1697 | video = kmalloc(sizeof(struct acpi_video_bus), GFP_KERNEL); | 1809 | video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL); |
1698 | if (!video) | 1810 | if (!video) |
1699 | return -ENOMEM; | 1811 | return -ENOMEM; |
1700 | memset(video, 0, sizeof(struct acpi_video_bus)); | ||
1701 | 1812 | ||
1702 | video->device = device; | 1813 | video->device = device; |
1703 | strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME); | 1814 | strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME); |
@@ -1755,7 +1866,7 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type) | |||
1755 | if (!device || !acpi_driver_data(device)) | 1866 | if (!device || !acpi_driver_data(device)) |
1756 | return -EINVAL; | 1867 | return -EINVAL; |
1757 | 1868 | ||
1758 | video = (struct acpi_video_bus *)acpi_driver_data(device); | 1869 | video = acpi_driver_data(device); |
1759 | 1870 | ||
1760 | acpi_video_bus_stop_devices(video); | 1871 | acpi_video_bus_stop_devices(video); |
1761 | 1872 | ||