aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2009-04-05 01:40:06 -0400
committerLen Brown <len.brown@intel.com>2009-04-05 01:40:06 -0400
commit12648810506eaa063dc23b66514fbb4796f34312 (patch)
tree4cd16290c9e1350d946a92ca8d5624cdd683b739
parent7329e9356e5b46e11a1781dff2dc64c2e3284884 (diff)
parent03ae61dd5701092aabb60a8cae9929dbf8dc25c6 (diff)
Merge branch 'video' into release
Conflicts: drivers/acpi/video.c Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r--drivers/acpi/video.c279
-rw-r--r--drivers/acpi/video_detect.c3
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c5
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c2
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h4
-rw-r--r--drivers/gpu/drm/i915/i915_opregion.c65
-rw-r--r--include/acpi/video.h11
7 files changed, 306 insertions, 63 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 5259d502add6..100c8eeaa5dd 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -37,6 +37,8 @@
37#include <linux/thermal.h> 37#include <linux/thermal.h>
38#include <linux/video_output.h> 38#include <linux/video_output.h>
39#include <linux/sort.h> 39#include <linux/sort.h>
40#include <linux/pci.h>
41#include <linux/pci_ids.h>
40#include <asm/uaccess.h> 42#include <asm/uaccess.h>
41 43
42#include <acpi/acpi_bus.h> 44#include <acpi/acpi_bus.h>
@@ -162,16 +164,26 @@ struct acpi_video_device_cap {
162 u8 _BCL:1; /*Query list of brightness control levels supported */ 164 u8 _BCL:1; /*Query list of brightness control levels supported */
163 u8 _BCM:1; /*Set the brightness level */ 165 u8 _BCM:1; /*Set the brightness level */
164 u8 _BQC:1; /* Get current brightness level */ 166 u8 _BQC:1; /* Get current brightness level */
167 u8 _BCQ:1; /* Some buggy BIOS uses _BCQ instead of _BQC */
165 u8 _DDC:1; /*Return the EDID for this device */ 168 u8 _DDC:1; /*Return the EDID for this device */
166 u8 _DCS:1; /*Return status of output device */ 169 u8 _DCS:1; /*Return status of output device */
167 u8 _DGS:1; /*Query graphics state */ 170 u8 _DGS:1; /*Query graphics state */
168 u8 _DSS:1; /*Device state set */ 171 u8 _DSS:1; /*Device state set */
169}; 172};
170 173
174struct acpi_video_brightness_flags {
175 u8 _BCL_no_ac_battery_levels:1; /* no AC/Battery levels in _BCL */
176 u8 _BCL_reversed:1; /* _BCL package is in a reversed order*/
177 u8 _BCL_use_index:1; /* levels in _BCL are index values */
178 u8 _BCM_use_index:1; /* input of _BCM is an index value */
179 u8 _BQC_use_index:1; /* _BQC returns an index value */
180};
181
171struct acpi_video_device_brightness { 182struct acpi_video_device_brightness {
172 int curr; 183 int curr;
173 int count; 184 int count;
174 int *levels; 185 int *levels;
186 struct acpi_video_brightness_flags flags;
175}; 187};
176 188
177struct acpi_video_device { 189struct acpi_video_device {
@@ -294,7 +306,7 @@ static int acpi_video_device_lcd_get_level_current(
294 unsigned long long *level); 306 unsigned long long *level);
295static int acpi_video_get_next_level(struct acpi_video_device *device, 307static int acpi_video_get_next_level(struct acpi_video_device *device,
296 u32 level_current, u32 event); 308 u32 level_current, u32 event);
297static void acpi_video_switch_brightness(struct acpi_video_device *device, 309static int acpi_video_switch_brightness(struct acpi_video_device *device,
298 int event); 310 int event);
299static int acpi_video_device_get_state(struct acpi_video_device *device, 311static int acpi_video_device_get_state(struct acpi_video_device *device,
300 unsigned long long *state); 312 unsigned long long *state);
@@ -308,7 +320,9 @@ static int acpi_video_get_brightness(struct backlight_device *bd)
308 int i; 320 int i;
309 struct acpi_video_device *vd = 321 struct acpi_video_device *vd =
310 (struct acpi_video_device *)bl_get_data(bd); 322 (struct acpi_video_device *)bl_get_data(bd);
311 acpi_video_device_lcd_get_level_current(vd, &cur_level); 323
324 if (acpi_video_device_lcd_get_level_current(vd, &cur_level))
325 return -EINVAL;
312 for (i = 2; i < vd->brightness->count; i++) { 326 for (i = 2; i < vd->brightness->count; i++) {
313 if (vd->brightness->levels[i] == cur_level) 327 if (vd->brightness->levels[i] == cur_level)
314 /* The first two entries are special - see page 575 328 /* The first two entries are special - see page 575
@@ -320,12 +334,12 @@ static int acpi_video_get_brightness(struct backlight_device *bd)
320 334
321static int acpi_video_set_brightness(struct backlight_device *bd) 335static int acpi_video_set_brightness(struct backlight_device *bd)
322{ 336{
323 int request_level = bd->props.brightness+2; 337 int request_level = bd->props.brightness + 2;
324 struct acpi_video_device *vd = 338 struct acpi_video_device *vd =
325 (struct acpi_video_device *)bl_get_data(bd); 339 (struct acpi_video_device *)bl_get_data(bd);
326 acpi_video_device_lcd_set_level(vd, 340
327 vd->brightness->levels[request_level]); 341 return acpi_video_device_lcd_set_level(vd,
328 return 0; 342 vd->brightness->levels[request_level]);
329} 343}
330 344
331static struct backlight_ops acpi_backlight_ops = { 345static struct backlight_ops acpi_backlight_ops = {
@@ -376,7 +390,8 @@ static int video_get_cur_state(struct thermal_cooling_device *cdev, unsigned
376 unsigned long long level; 390 unsigned long long level;
377 int offset; 391 int offset;
378 392
379 acpi_video_device_lcd_get_level_current(video, &level); 393 if (acpi_video_device_lcd_get_level_current(video, &level))
394 return -EINVAL;
380 for (offset = 2; offset < video->brightness->count; offset++) 395 for (offset = 2; offset < video->brightness->count; offset++)
381 if (level == video->brightness->levels[offset]) { 396 if (level == video->brightness->levels[offset]) {
382 *state = video->brightness->count - offset - 1; 397 *state = video->brightness->count - offset - 1;
@@ -483,34 +498,68 @@ acpi_video_device_lcd_query_levels(struct acpi_video_device *device,
483static int 498static int
484acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level) 499acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
485{ 500{
486 int status = AE_OK; 501 int status;
487 union acpi_object arg0 = { ACPI_TYPE_INTEGER }; 502 union acpi_object arg0 = { ACPI_TYPE_INTEGER };
488 struct acpi_object_list args = { 1, &arg0 }; 503 struct acpi_object_list args = { 1, &arg0 };
489 int state; 504 int state;
490 505
491
492 arg0.integer.value = level; 506 arg0.integer.value = level;
493 507
494 if (device->cap._BCM) 508 status = acpi_evaluate_object(device->dev->handle, "_BCM",
495 status = acpi_evaluate_object(device->dev->handle, "_BCM", 509 &args, NULL);
496 &args, NULL); 510 if (ACPI_FAILURE(status)) {
511 ACPI_ERROR((AE_INFO, "Evaluating _BCM failed"));
512 return -EIO;
513 }
514
497 device->brightness->curr = level; 515 device->brightness->curr = level;
498 for (state = 2; state < device->brightness->count; state++) 516 for (state = 2; state < device->brightness->count; state++)
499 if (level == device->brightness->levels[state]) 517 if (level == device->brightness->levels[state]) {
500 device->backlight->props.brightness = state - 2; 518 if (device->backlight)
519 device->backlight->props.brightness = state - 2;
520 return 0;
521 }
501 522
502 return status; 523 ACPI_ERROR((AE_INFO, "Current brightness invalid"));
524 return -EINVAL;
503} 525}
504 526
505static int 527static int
506acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, 528acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
507 unsigned long long *level) 529 unsigned long long *level)
508{ 530{
509 if (device->cap._BQC) 531 acpi_status status = AE_OK;
510 return acpi_evaluate_integer(device->dev->handle, "_BQC", NULL, 532
511 level); 533 if (device->cap._BQC || device->cap._BCQ) {
534 char *buf = device->cap._BQC ? "_BQC" : "_BCQ";
535
536 status = acpi_evaluate_integer(device->dev->handle, buf,
537 NULL, level);
538 if (ACPI_SUCCESS(status)) {
539 if (device->brightness->flags._BQC_use_index) {
540 if (device->brightness->flags._BCL_reversed)
541 *level = device->brightness->count
542 - 3 - (*level);
543 *level = device->brightness->levels[*level + 2];
544
545 }
546 device->brightness->curr = *level;
547 return 0;
548 } else {
549 /* Fixme:
550 * should we return an error or ignore this failure?
551 * dev->brightness->curr is a cached value which stores
552 * the correct current backlight level in most cases.
553 * ACPI video backlight still works w/ buggy _BQC.
554 * http://bugzilla.kernel.org/show_bug.cgi?id=12233
555 */
556 ACPI_WARNING((AE_INFO, "Evaluating %s failed", buf));
557 device->cap._BQC = device->cap._BCQ = 0;
558 }
559 }
560
512 *level = device->brightness->curr; 561 *level = device->brightness->curr;
513 return AE_OK; 562 return 0;
514} 563}
515 564
516static int 565static int
@@ -659,9 +708,11 @@ static int
659acpi_video_init_brightness(struct acpi_video_device *device) 708acpi_video_init_brightness(struct acpi_video_device *device)
660{ 709{
661 union acpi_object *obj = NULL; 710 union acpi_object *obj = NULL;
662 int i, max_level = 0, count = 0; 711 int i, max_level = 0, count = 0, level_ac_battery = 0;
712 unsigned long long level, level_old;
663 union acpi_object *o; 713 union acpi_object *o;
664 struct acpi_video_device_brightness *br = NULL; 714 struct acpi_video_device_brightness *br = NULL;
715 int result = -EINVAL;
665 716
666 if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) { 717 if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) {
667 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available " 718 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available "
@@ -675,13 +726,16 @@ acpi_video_init_brightness(struct acpi_video_device *device)
675 br = kzalloc(sizeof(*br), GFP_KERNEL); 726 br = kzalloc(sizeof(*br), GFP_KERNEL);
676 if (!br) { 727 if (!br) {
677 printk(KERN_ERR "can't allocate memory\n"); 728 printk(KERN_ERR "can't allocate memory\n");
729 result = -ENOMEM;
678 goto out; 730 goto out;
679 } 731 }
680 732
681 br->levels = kmalloc(obj->package.count * sizeof *(br->levels), 733 br->levels = kmalloc((obj->package.count + 2) * sizeof *(br->levels),
682 GFP_KERNEL); 734 GFP_KERNEL);
683 if (!br->levels) 735 if (!br->levels) {
736 result = -ENOMEM;
684 goto out_free; 737 goto out_free;
738 }
685 739
686 for (i = 0; i < obj->package.count; i++) { 740 for (i = 0; i < obj->package.count; i++) {
687 o = (union acpi_object *)&obj->package.elements[i]; 741 o = (union acpi_object *)&obj->package.elements[i];
@@ -696,18 +750,86 @@ acpi_video_init_brightness(struct acpi_video_device *device)
696 count++; 750 count++;
697 } 751 }
698 752
699 /* don't sort the first two brightness levels */ 753 /*
700 sort(&br->levels[2], count - 2, sizeof(br->levels[2]), 754 * some buggy BIOS don't export the levels
701 acpi_video_cmp_level, NULL); 755 * when machine is on AC/Battery in _BCL package.
702 756 * In this case, the first two elements in _BCL packages
703 if (count < 2) 757 * are also supported brightness levels that OS should take care of.
704 goto out_free_levels; 758 */
759 for (i = 2; i < count; i++)
760 if (br->levels[i] == br->levels[0] ||
761 br->levels[i] == br->levels[1])
762 level_ac_battery++;
763
764 if (level_ac_battery < 2) {
765 level_ac_battery = 2 - level_ac_battery;
766 br->flags._BCL_no_ac_battery_levels = 1;
767 for (i = (count - 1 + level_ac_battery); i >= 2; i--)
768 br->levels[i] = br->levels[i - level_ac_battery];
769 count += level_ac_battery;
770 } else if (level_ac_battery > 2)
771 ACPI_ERROR((AE_INFO, "Too many duplicates in _BCL package\n"));
772
773 /* Check if the _BCL package is in a reversed order */
774 if (max_level == br->levels[2]) {
775 br->flags._BCL_reversed = 1;
776 sort(&br->levels[2], count - 2, sizeof(br->levels[2]),
777 acpi_video_cmp_level, NULL);
778 } else if (max_level != br->levels[count - 1])
779 ACPI_ERROR((AE_INFO,
780 "Found unordered _BCL package\n"));
705 781
706 br->count = count; 782 br->count = count;
707 device->brightness = br; 783 device->brightness = br;
708 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "found %d brightness levels\n", count)); 784
785 /* Check the input/output of _BQC/_BCL/_BCM */
786 if ((max_level < 100) && (max_level <= (count - 2)))
787 br->flags._BCL_use_index = 1;
788
789 /*
790 * _BCM is always consistent with _BCL,
791 * at least for all the laptops we have ever seen.
792 */
793 br->flags._BCM_use_index = br->flags._BCL_use_index;
794
795 /* _BQC uses INDEX while _BCL uses VALUE in some laptops */
796 br->curr = max_level;
797 result = acpi_video_device_lcd_get_level_current(device, &level_old);
798 if (result)
799 goto out_free_levels;
800
801 result = acpi_video_device_lcd_set_level(device, br->curr);
802 if (result)
803 goto out_free_levels;
804
805 result = acpi_video_device_lcd_get_level_current(device, &level);
806 if (result)
807 goto out_free_levels;
808
809 if ((level != level_old) && !br->flags._BCM_use_index) {
810 /* Note:
811 * This piece of code does not work correctly if the current
812 * brightness levels is 0.
813 * But I guess boxes that boot with such a dark screen are rare
814 * and no more code is needed to cover this specifial case.
815 */
816
817 if (level_ac_battery != 2) {
818 /*
819 * For now, we don't support the _BCL like this:
820 * 16, 15, 0, 1, 2, 3, ..., 14, 15, 16
821 * because we may mess up the index returned by _BQC.
822 * Plus: we have not got a box like this.
823 */
824 ACPI_ERROR((AE_INFO, "_BCL not supported\n"));
825 }
826 br->flags._BQC_use_index = 1;
827 }
828
829 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
830 "found %d brightness levels\n", count - 2));
709 kfree(obj); 831 kfree(obj);
710 return max_level; 832 return result;
711 833
712out_free_levels: 834out_free_levels:
713 kfree(br->levels); 835 kfree(br->levels);
@@ -716,7 +838,7 @@ out_free:
716out: 838out:
717 device->brightness = NULL; 839 device->brightness = NULL;
718 kfree(obj); 840 kfree(obj);
719 return 0; 841 return result;
720} 842}
721 843
722/* 844/*
@@ -733,7 +855,6 @@ out:
733static void acpi_video_device_find_cap(struct acpi_video_device *device) 855static void acpi_video_device_find_cap(struct acpi_video_device *device)
734{ 856{
735 acpi_handle h_dummy1; 857 acpi_handle h_dummy1;
736 u32 max_level = 0;
737 858
738 859
739 memset(&device->cap, 0, sizeof(device->cap)); 860 memset(&device->cap, 0, sizeof(device->cap));
@@ -749,6 +870,12 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
749 } 870 }
750 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle,"_BQC",&h_dummy1))) 871 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle,"_BQC",&h_dummy1)))
751 device->cap._BQC = 1; 872 device->cap._BQC = 1;
873 else if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCQ",
874 &h_dummy1))) {
875 printk(KERN_WARNING FW_BUG "_BCQ is used instead of _BQC\n");
876 device->cap._BCQ = 1;
877 }
878
752 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) { 879 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) {
753 device->cap._DDC = 1; 880 device->cap._DDC = 1;
754 } 881 }
@@ -762,13 +889,14 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
762 device->cap._DSS = 1; 889 device->cap._DSS = 1;
763 } 890 }
764 891
765 if (acpi_video_backlight_support()) 892 if (acpi_video_backlight_support()) {
766 max_level = acpi_video_init_brightness(device);
767
768 if (device->cap._BCL && device->cap._BCM && max_level > 0) {
769 int result; 893 int result;
770 static int count = 0; 894 static int count = 0;
771 char *name; 895 char *name;
896
897 result = acpi_video_init_brightness(device);
898 if (result)
899 return;
772 name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); 900 name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
773 if (!name) 901 if (!name)
774 return; 902 return;
@@ -777,18 +905,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
777 device->backlight = backlight_device_register(name, 905 device->backlight = backlight_device_register(name,
778 NULL, device, &acpi_backlight_ops); 906 NULL, device, &acpi_backlight_ops);
779 device->backlight->props.max_brightness = device->brightness->count-3; 907 device->backlight->props.max_brightness = device->brightness->count-3;
780 /*
781 * If there exists the _BQC object, the _BQC object will be
782 * called to get the current backlight brightness. Otherwise
783 * the brightness will be set to the maximum.
784 */
785 if (device->cap._BQC)
786 device->backlight->props.brightness =
787 acpi_video_get_brightness(device->backlight);
788 else
789 device->backlight->props.brightness =
790 device->backlight->props.max_brightness;
791 backlight_update_status(device->backlight);
792 kfree(name); 908 kfree(name);
793 909
794 device->cdev = thermal_cooling_device_register("LCD", 910 device->cdev = thermal_cooling_device_register("LCD",
@@ -1065,13 +1181,12 @@ acpi_video_device_write_brightness(struct file *file,
1065 /* validate through the list of available levels */ 1181 /* validate through the list of available levels */
1066 for (i = 2; i < dev->brightness->count; i++) 1182 for (i = 2; i < dev->brightness->count; i++)
1067 if (level == dev->brightness->levels[i]) { 1183 if (level == dev->brightness->levels[i]) {
1068 if (ACPI_SUCCESS 1184 if (!acpi_video_device_lcd_set_level(dev, level))
1069 (acpi_video_device_lcd_set_level(dev, level))) 1185 return count;
1070 dev->brightness->curr = level;
1071 break; 1186 break;
1072 } 1187 }
1073 1188
1074 return count; 1189 return -EINVAL;
1075} 1190}
1076 1191
1077static int acpi_video_device_EDID_seq_show(struct seq_file *seq, void *offset) 1192static int acpi_video_device_EDID_seq_show(struct seq_file *seq, void *offset)
@@ -1753,15 +1868,29 @@ acpi_video_get_next_level(struct acpi_video_device *device,
1753 } 1868 }
1754} 1869}
1755 1870
1756static void 1871static int
1757acpi_video_switch_brightness(struct acpi_video_device *device, int event) 1872acpi_video_switch_brightness(struct acpi_video_device *device, int event)
1758{ 1873{
1759 unsigned long long level_current, level_next; 1874 unsigned long long level_current, level_next;
1875 int result = -EINVAL;
1876
1760 if (!device->brightness) 1877 if (!device->brightness)
1761 return; 1878 goto out;
1762 acpi_video_device_lcd_get_level_current(device, &level_current); 1879
1880 result = acpi_video_device_lcd_get_level_current(device,
1881 &level_current);
1882 if (result)
1883 goto out;
1884
1763 level_next = acpi_video_get_next_level(device, level_current, event); 1885 level_next = acpi_video_get_next_level(device, level_current, event);
1764 acpi_video_device_lcd_set_level(device, level_next); 1886
1887 result = acpi_video_device_lcd_set_level(device, level_next);
1888
1889out:
1890 if (result)
1891 printk(KERN_ERR PREFIX "Failed to switch the brightness\n");
1892
1893 return result;
1765} 1894}
1766 1895
1767static int 1896static int
@@ -2128,7 +2257,27 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type)
2128 return 0; 2257 return 0;
2129} 2258}
2130 2259
2131static int __init acpi_video_init(void) 2260static int __init intel_opregion_present(void)
2261{
2262#if defined(CONFIG_DRM_I915) || defined(CONFIG_DRM_I915_MODULE)
2263 struct pci_dev *dev = NULL;
2264 u32 address;
2265
2266 for_each_pci_dev(dev) {
2267 if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
2268 continue;
2269 if (dev->vendor != PCI_VENDOR_ID_INTEL)
2270 continue;
2271 pci_read_config_dword(dev, 0xfc, &address);
2272 if (!address)
2273 continue;
2274 return 1;
2275 }
2276#endif
2277 return 0;
2278}
2279
2280int acpi_video_register(void)
2132{ 2281{
2133 int result = 0; 2282 int result = 0;
2134 2283
@@ -2145,6 +2294,22 @@ static int __init acpi_video_init(void)
2145 2294
2146 return 0; 2295 return 0;
2147} 2296}
2297EXPORT_SYMBOL(acpi_video_register);
2298
2299/*
2300 * This is kind of nasty. Hardware using Intel chipsets may require
2301 * the video opregion code to be run first in order to initialise
2302 * state before any ACPI video calls are made. To handle this we defer
2303 * registration of the video class until the opregion code has run.
2304 */
2305
2306static int __init acpi_video_init(void)
2307{
2308 if (intel_opregion_present())
2309 return 0;
2310
2311 return acpi_video_register();
2312}
2148 2313
2149static void __exit acpi_video_exit(void) 2314static void __exit acpi_video_exit(void)
2150{ 2315{
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index 50e3d2dbf3af..09737275e25f 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -55,6 +55,9 @@ acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context,
55 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found generic backlight " 55 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found generic backlight "
56 "support\n")); 56 "support\n"));
57 *cap |= ACPI_VIDEO_BACKLIGHT; 57 *cap |= ACPI_VIDEO_BACKLIGHT;
58 if (ACPI_FAILURE(acpi_get_handle(handle, "_BQC", &h_dummy)))
59 printk(KERN_WARNING FW_BUG PREFIX "ACPI brightness "
60 "control misses _BQC function\n");
58 /* We have backlight support, no need to scan further */ 61 /* We have backlight support, no need to scan further */
59 return AE_CTRL_TERMINATE; 62 return AE_CTRL_TERMINATE;
60 } 63 }
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 6d21b9e48b89..638686904e06 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1144,8 +1144,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
1144 if (!IS_I945G(dev) && !IS_I945GM(dev)) 1144 if (!IS_I945G(dev) && !IS_I945GM(dev))
1145 pci_enable_msi(dev->pdev); 1145 pci_enable_msi(dev->pdev);
1146 1146
1147 intel_opregion_init(dev);
1148
1149 spin_lock_init(&dev_priv->user_irq_lock); 1147 spin_lock_init(&dev_priv->user_irq_lock);
1150 dev_priv->user_irq_refcount = 0; 1148 dev_priv->user_irq_refcount = 0;
1151 1149
@@ -1164,6 +1162,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
1164 } 1162 }
1165 } 1163 }
1166 1164
1165 /* Must be done after probing outputs */
1166 intel_opregion_init(dev, 0);
1167
1167 return 0; 1168 return 0;
1168 1169
1169out_iomapfree: 1170out_iomapfree:
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index b293ef0bae71..209592fdb7e7 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -99,7 +99,7 @@ static int i915_resume(struct drm_device *dev)
99 99
100 i915_restore_state(dev); 100 i915_restore_state(dev);
101 101
102 intel_opregion_init(dev); 102 intel_opregion_init(dev, 1);
103 103
104 /* KMS EnterVT equivalent */ 104 /* KMS EnterVT equivalent */
105 if (drm_core_check_feature(dev, DRIVER_MODESET)) { 105 if (drm_core_check_feature(dev, DRIVER_MODESET)) {
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index d6cc9861e0a1..b9a92c250b91 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -659,12 +659,12 @@ extern int i915_restore_state(struct drm_device *dev);
659 659
660#ifdef CONFIG_ACPI 660#ifdef CONFIG_ACPI
661/* i915_opregion.c */ 661/* i915_opregion.c */
662extern int intel_opregion_init(struct drm_device *dev); 662extern int intel_opregion_init(struct drm_device *dev, int resume);
663extern void intel_opregion_free(struct drm_device *dev); 663extern void intel_opregion_free(struct drm_device *dev);
664extern void opregion_asle_intr(struct drm_device *dev); 664extern void opregion_asle_intr(struct drm_device *dev);
665extern void opregion_enable_asle(struct drm_device *dev); 665extern void opregion_enable_asle(struct drm_device *dev);
666#else 666#else
667static inline int intel_opregion_init(struct drm_device *dev) { return 0; } 667static inline int intel_opregion_init(struct drm_device *dev, int resume) { return 0; }
668static inline void intel_opregion_free(struct drm_device *dev) { return; } 668static inline void intel_opregion_free(struct drm_device *dev) { return; }
669static inline void opregion_asle_intr(struct drm_device *dev) { return; } 669static inline void opregion_asle_intr(struct drm_device *dev) { return; }
670static inline void opregion_enable_asle(struct drm_device *dev) { return; } 670static inline void opregion_enable_asle(struct drm_device *dev) { return; }
diff --git a/drivers/gpu/drm/i915/i915_opregion.c b/drivers/gpu/drm/i915/i915_opregion.c
index ff012835a386..69427722d20e 100644
--- a/drivers/gpu/drm/i915/i915_opregion.c
+++ b/drivers/gpu/drm/i915/i915_opregion.c
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28#include <linux/acpi.h> 28#include <linux/acpi.h>
29#include <acpi/video.h>
29 30
30#include "drmP.h" 31#include "drmP.h"
31#include "i915_drm.h" 32#include "i915_drm.h"
@@ -136,6 +137,12 @@ struct opregion_asle {
136 137
137#define ASLE_CBLV_VALID (1<<31) 138#define ASLE_CBLV_VALID (1<<31)
138 139
140#define ACPI_OTHER_OUTPUT (0<<8)
141#define ACPI_VGA_OUTPUT (1<<8)
142#define ACPI_TV_OUTPUT (2<<8)
143#define ACPI_DIGITAL_OUTPUT (3<<8)
144#define ACPI_LVDS_OUTPUT (4<<8)
145
139static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) 146static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
140{ 147{
141 struct drm_i915_private *dev_priv = dev->dev_private; 148 struct drm_i915_private *dev_priv = dev->dev_private;
@@ -282,7 +289,58 @@ static struct notifier_block intel_opregion_notifier = {
282 .notifier_call = intel_opregion_video_event, 289 .notifier_call = intel_opregion_video_event,
283}; 290};
284 291
285int intel_opregion_init(struct drm_device *dev) 292/*
293 * Initialise the DIDL field in opregion. This passes a list of devices to
294 * the firmware. Values are defined by section B.4.2 of the ACPI specification
295 * (version 3)
296 */
297
298static void intel_didl_outputs(struct drm_device *dev)
299{
300 struct drm_i915_private *dev_priv = dev->dev_private;
301 struct intel_opregion *opregion = &dev_priv->opregion;
302 struct drm_connector *connector;
303 int i = 0;
304
305 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
306 int output_type = ACPI_OTHER_OUTPUT;
307 if (i >= 8) {
308 dev_printk (KERN_ERR, &dev->pdev->dev,
309 "More than 8 outputs detected\n");
310 return;
311 }
312 switch (connector->connector_type) {
313 case DRM_MODE_CONNECTOR_VGA:
314 case DRM_MODE_CONNECTOR_DVIA:
315 output_type = ACPI_VGA_OUTPUT;
316 break;
317 case DRM_MODE_CONNECTOR_Composite:
318 case DRM_MODE_CONNECTOR_SVIDEO:
319 case DRM_MODE_CONNECTOR_Component:
320 case DRM_MODE_CONNECTOR_9PinDIN:
321 output_type = ACPI_TV_OUTPUT;
322 break;
323 case DRM_MODE_CONNECTOR_DVII:
324 case DRM_MODE_CONNECTOR_DVID:
325 case DRM_MODE_CONNECTOR_DisplayPort:
326 case DRM_MODE_CONNECTOR_HDMIA:
327 case DRM_MODE_CONNECTOR_HDMIB:
328 output_type = ACPI_DIGITAL_OUTPUT;
329 break;
330 case DRM_MODE_CONNECTOR_LVDS:
331 output_type = ACPI_LVDS_OUTPUT;
332 break;
333 }
334 opregion->acpi->didl[i] |= (1<<31) | output_type | i;
335 i++;
336 }
337
338 /* If fewer than 8 outputs, the list must be null terminated */
339 if (i < 8)
340 opregion->acpi->didl[i] = 0;
341}
342
343int intel_opregion_init(struct drm_device *dev, int resume)
286{ 344{
287 struct drm_i915_private *dev_priv = dev->dev_private; 345 struct drm_i915_private *dev_priv = dev->dev_private;
288 struct intel_opregion *opregion = &dev_priv->opregion; 346 struct intel_opregion *opregion = &dev_priv->opregion;
@@ -312,6 +370,11 @@ int intel_opregion_init(struct drm_device *dev)
312 if (mboxes & MBOX_ACPI) { 370 if (mboxes & MBOX_ACPI) {
313 DRM_DEBUG("Public ACPI methods supported\n"); 371 DRM_DEBUG("Public ACPI methods supported\n");
314 opregion->acpi = base + OPREGION_ACPI_OFFSET; 372 opregion->acpi = base + OPREGION_ACPI_OFFSET;
373 if (drm_core_check_feature(dev, DRIVER_MODESET)) {
374 intel_didl_outputs(dev);
375 if (!resume)
376 acpi_video_register();
377 }
315 } else { 378 } else {
316 DRM_DEBUG("Public ACPI methods not supported\n"); 379 DRM_DEBUG("Public ACPI methods not supported\n");
317 err = -ENOTSUPP; 380 err = -ENOTSUPP;
diff --git a/include/acpi/video.h b/include/acpi/video.h
new file mode 100644
index 000000000000..f0275bb79ce4
--- /dev/null
+++ b/include/acpi/video.h
@@ -0,0 +1,11 @@
1#ifndef __ACPI_VIDEO_H
2#define __ACPI_VIDEO_H
3
4#if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE)
5extern int acpi_video_register(void);
6#else
7static inline int acpi_video_register(void) { return 0; }
8#endif
9
10#endif
11