aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-10-27 20:20:14 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-10-27 20:20:14 -0400
commit975bcabb05436d8b99214a2293d1d5b9c0b0ca08 (patch)
treea3c1049d5029ed6726ec4135ca18b4d9595d2b55
parentdd6c26be3bb3e98d4811780f831bbc246dae54c8 (diff)
parent1bdb71af7f1388fd4b305134035008a81f2032b8 (diff)
Merge branch 'acpi-video'
* acpi-video: ACPI: Add Toshiba NB100 to Vista _OSI blacklist ACPI / video: Ignore BIOS initial backlight value for HP 250 G1 ACPI / video: Add Lenovo IdeaPad Yoga 13 to acpi video detect blacklist thinkpad-acpi: fix handle locate for video and query of _BCL ACPI / video: Do not register backlight if win8 and native interface exists ACPI / video: seperate backlight control and event interface backlight: introduce backlight_device_registered ACPI: add missing win8 OSI comment to blacklist ACPI: update win8 OSI blacklist
-rw-r--r--drivers/acpi/blacklist.c61
-rw-r--r--drivers/acpi/internal.h4
-rw-r--r--drivers/acpi/video.c465
-rw-r--r--drivers/acpi/video_detect.c12
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c31
-rw-r--r--drivers/video/backlight/backlight.c31
-rw-r--r--include/linux/backlight.h4
7 files changed, 403 insertions, 205 deletions
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index 9515f18898b2..b7fd1aeb6c42 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -274,6 +274,19 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
274 }, 274 },
275 }, 275 },
276 { 276 {
277 .callback = dmi_disable_osi_vista,
278 .ident = "Toshiba NB100",
279 .matches = {
280 DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
281 DMI_MATCH(DMI_PRODUCT_NAME, "NB100"),
282 },
283 },
284
285 /*
286 * The following machines have broken backlight support when reporting
287 * the Windows 2012 OSI, so disable it until their support is fixed.
288 */
289 {
277 .callback = dmi_disable_osi_win8, 290 .callback = dmi_disable_osi_win8,
278 .ident = "ASUS Zenbook Prime UX31A", 291 .ident = "ASUS Zenbook Prime UX31A",
279 .matches = { 292 .matches = {
@@ -297,6 +310,54 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
297 DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"), 310 DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"),
298 }, 311 },
299 }, 312 },
313 {
314 .callback = dmi_disable_osi_win8,
315 .ident = "ThinkPad Edge E530",
316 .matches = {
317 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
318 DMI_MATCH(DMI_PRODUCT_VERSION, "3259CTO"),
319 },
320 },
321 {
322 .callback = dmi_disable_osi_win8,
323 .ident = "ThinkPad Edge E530",
324 .matches = {
325 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
326 DMI_MATCH(DMI_PRODUCT_VERSION, "3259HJG"),
327 },
328 },
329 {
330 .callback = dmi_disable_osi_win8,
331 .ident = "Acer Aspire V5-573G",
332 .matches = {
333 DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"),
334 DMI_MATCH(DMI_PRODUCT_VERSION, "V5-573G/Dazzle_HW"),
335 },
336 },
337 {
338 .callback = dmi_disable_osi_win8,
339 .ident = "Acer Aspire V5-572G",
340 .matches = {
341 DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"),
342 DMI_MATCH(DMI_PRODUCT_VERSION, "V5-572G/Dazzle_CX"),
343 },
344 },
345 {
346 .callback = dmi_disable_osi_win8,
347 .ident = "ThinkPad T431s",
348 .matches = {
349 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
350 DMI_MATCH(DMI_PRODUCT_VERSION, "20AACTO1WW"),
351 },
352 },
353 {
354 .callback = dmi_disable_osi_win8,
355 .ident = "ThinkPad T430",
356 .matches = {
357 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
358 DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"),
359 },
360 },
300 361
301 /* 362 /*
302 * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. 363 * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 20f423337e1f..e9304dc7ebfa 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -169,9 +169,7 @@ int acpi_create_platform_device(struct acpi_device *adev,
169 Video 169 Video
170 -------------------------------------------------------------------------- */ 170 -------------------------------------------------------------------------- */
171#if defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE) 171#if defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE)
172bool acpi_video_backlight_quirks(void); 172bool acpi_osi_is_win8(void);
173#else
174static inline bool acpi_video_backlight_quirks(void) { return false; }
175#endif 173#endif
176 174
177#endif /* _ACPI_INTERNAL_H_ */ 175#endif /* _ACPI_INTERNAL_H_ */
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index aebcf6355df4..38c3a28d6392 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -88,7 +88,16 @@ module_param(allow_duplicates, bool, 0644);
88static bool use_bios_initial_backlight = 1; 88static bool use_bios_initial_backlight = 1;
89module_param(use_bios_initial_backlight, bool, 0644); 89module_param(use_bios_initial_backlight, bool, 0644);
90 90
91/*
92 * For Windows 8 systems: if set ture and the GPU driver has
93 * registered a backlight interface, skip registering ACPI video's.
94 */
95static bool use_native_backlight = false;
96module_param(use_native_backlight, bool, 0644);
97
91static int register_count; 98static int register_count;
99static struct mutex video_list_lock;
100static struct list_head video_bus_head;
92static int acpi_video_bus_add(struct acpi_device *device); 101static int acpi_video_bus_add(struct acpi_device *device);
93static int acpi_video_bus_remove(struct acpi_device *device); 102static int acpi_video_bus_remove(struct acpi_device *device);
94static void acpi_video_bus_notify(struct acpi_device *device, u32 event); 103static void acpi_video_bus_notify(struct acpi_device *device, u32 event);
@@ -157,6 +166,7 @@ struct acpi_video_bus {
157 struct acpi_video_bus_flags flags; 166 struct acpi_video_bus_flags flags;
158 struct list_head video_device_list; 167 struct list_head video_device_list;
159 struct mutex device_list_lock; /* protects video_device_list */ 168 struct mutex device_list_lock; /* protects video_device_list */
169 struct list_head entry;
160 struct input_dev *input; 170 struct input_dev *input;
161 char phys[32]; /* for input device */ 171 char phys[32]; /* for input device */
162 struct notifier_block pm_nb; 172 struct notifier_block pm_nb;
@@ -229,6 +239,14 @@ static int acpi_video_get_next_level(struct acpi_video_device *device,
229static int acpi_video_switch_brightness(struct acpi_video_device *device, 239static int acpi_video_switch_brightness(struct acpi_video_device *device,
230 int event); 240 int event);
231 241
242static bool acpi_video_verify_backlight_support(void)
243{
244 if (acpi_osi_is_win8() && use_native_backlight &&
245 backlight_device_registered(BACKLIGHT_RAW))
246 return false;
247 return acpi_video_backlight_support();
248}
249
232/* backlight device sysfs support */ 250/* backlight device sysfs support */
233static int acpi_video_get_brightness(struct backlight_device *bd) 251static int acpi_video_get_brightness(struct backlight_device *bd)
234{ 252{
@@ -486,6 +504,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
486 DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion m4 Notebook PC"), 504 DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion m4 Notebook PC"),
487 }, 505 },
488 }, 506 },
507 {
508 .callback = video_ignore_initial_backlight,
509 .ident = "HP 250 G1",
510 .matches = {
511 DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
512 DMI_MATCH(DMI_PRODUCT_NAME, "HP 250 G1 Notebook PC"),
513 },
514 },
489 {} 515 {}
490}; 516};
491 517
@@ -884,79 +910,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
884 910
885 if (acpi_has_method(device->dev->handle, "_DDC")) 911 if (acpi_has_method(device->dev->handle, "_DDC"))
886 device->cap._DDC = 1; 912 device->cap._DDC = 1;
887
888 if (acpi_video_backlight_support()) {
889 struct backlight_properties props;
890 struct pci_dev *pdev;
891 acpi_handle acpi_parent;
892 struct device *parent = NULL;
893 int result;
894 static int count;
895 char *name;
896
897 result = acpi_video_init_brightness(device);
898 if (result)
899 return;
900 name = kasprintf(GFP_KERNEL, "acpi_video%d", count);
901 if (!name)
902 return;
903 count++;
904
905 acpi_get_parent(device->dev->handle, &acpi_parent);
906
907 pdev = acpi_get_pci_dev(acpi_parent);
908 if (pdev) {
909 parent = &pdev->dev;
910 pci_dev_put(pdev);
911 }
912
913 memset(&props, 0, sizeof(struct backlight_properties));
914 props.type = BACKLIGHT_FIRMWARE;
915 props.max_brightness = device->brightness->count - 3;
916 device->backlight = backlight_device_register(name,
917 parent,
918 device,
919 &acpi_backlight_ops,
920 &props);
921 kfree(name);
922 if (IS_ERR(device->backlight))
923 return;
924
925 /*
926 * Save current brightness level in case we have to restore it
927 * before acpi_video_device_lcd_set_level() is called next time.
928 */
929 device->backlight->props.brightness =
930 acpi_video_get_brightness(device->backlight);
931
932 device->cooling_dev = thermal_cooling_device_register("LCD",
933 device->dev, &video_cooling_ops);
934 if (IS_ERR(device->cooling_dev)) {
935 /*
936 * Set cooling_dev to NULL so we don't crash trying to
937 * free it.
938 * Also, why the hell we are returning early and
939 * not attempt to register video output if cooling
940 * device registration failed?
941 * -- dtor
942 */
943 device->cooling_dev = NULL;
944 return;
945 }
946
947 dev_info(&device->dev->dev, "registered as cooling_device%d\n",
948 device->cooling_dev->id);
949 result = sysfs_create_link(&device->dev->dev.kobj,
950 &device->cooling_dev->device.kobj,
951 "thermal_cooling");
952 if (result)
953 printk(KERN_ERR PREFIX "Create sysfs link\n");
954 result = sysfs_create_link(&device->cooling_dev->device.kobj,
955 &device->dev->dev.kobj, "device");
956 if (result)
957 printk(KERN_ERR PREFIX "Create sysfs link\n");
958
959 }
960} 913}
961 914
962/* 915/*
@@ -1143,13 +1096,6 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
1143 acpi_video_device_bind(video, data); 1096 acpi_video_device_bind(video, data);
1144 acpi_video_device_find_cap(data); 1097 acpi_video_device_find_cap(data);
1145 1098
1146 status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
1147 acpi_video_device_notify, data);
1148 if (ACPI_FAILURE(status))
1149 dev_err(&device->dev, "Error installing notify handler\n");
1150 else
1151 data->flags.notify = 1;
1152
1153 mutex_lock(&video->device_list_lock); 1099 mutex_lock(&video->device_list_lock);
1154 list_add_tail(&data->entry, &video->video_device_list); 1100 list_add_tail(&data->entry, &video->video_device_list);
1155 mutex_unlock(&video->device_list_lock); 1101 mutex_unlock(&video->device_list_lock);
@@ -1333,8 +1279,8 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event)
1333 unsigned long long level_current, level_next; 1279 unsigned long long level_current, level_next;
1334 int result = -EINVAL; 1280 int result = -EINVAL;
1335 1281
1336 /* no warning message if acpi_backlight=vendor is used */ 1282 /* no warning message if acpi_backlight=vendor or a quirk is used */
1337 if (!acpi_video_backlight_support()) 1283 if (!acpi_video_verify_backlight_support())
1338 return 0; 1284 return 0;
1339 1285
1340 if (!device->brightness) 1286 if (!device->brightness)
@@ -1454,64 +1400,6 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video,
1454 return status; 1400 return status;
1455} 1401}
1456 1402
1457static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
1458{
1459 acpi_status status;
1460
1461 if (!device || !device->video)
1462 return -ENOENT;
1463
1464 if (device->flags.notify) {
1465 status = acpi_remove_notify_handler(device->dev->handle,
1466 ACPI_DEVICE_NOTIFY, acpi_video_device_notify);
1467 if (ACPI_FAILURE(status))
1468 dev_err(&device->dev->dev,
1469 "Can't remove video notify handler\n");
1470 }
1471
1472 if (device->backlight) {
1473 backlight_device_unregister(device->backlight);
1474 device->backlight = NULL;
1475 }
1476 if (device->cooling_dev) {
1477 sysfs_remove_link(&device->dev->dev.kobj,
1478 "thermal_cooling");
1479 sysfs_remove_link(&device->cooling_dev->device.kobj,
1480 "device");
1481 thermal_cooling_device_unregister(device->cooling_dev);
1482 device->cooling_dev = NULL;
1483 }
1484
1485 return 0;
1486}
1487
1488static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
1489{
1490 int status;
1491 struct acpi_video_device *dev, *next;
1492
1493 mutex_lock(&video->device_list_lock);
1494
1495 list_for_each_entry_safe(dev, next, &video->video_device_list, entry) {
1496
1497 status = acpi_video_bus_put_one_device(dev);
1498 if (ACPI_FAILURE(status))
1499 printk(KERN_WARNING PREFIX
1500 "hhuuhhuu bug in acpi video driver.\n");
1501
1502 if (dev->brightness) {
1503 kfree(dev->brightness->levels);
1504 kfree(dev->brightness);
1505 }
1506 list_del(&dev->entry);
1507 kfree(dev);
1508 }
1509
1510 mutex_unlock(&video->device_list_lock);
1511
1512 return 0;
1513}
1514
1515/* acpi_video interface */ 1403/* acpi_video interface */
1516 1404
1517/* 1405/*
@@ -1521,13 +1409,13 @@ static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
1521static int acpi_video_bus_start_devices(struct acpi_video_bus *video) 1409static int acpi_video_bus_start_devices(struct acpi_video_bus *video)
1522{ 1410{
1523 return acpi_video_bus_DOS(video, 0, 1411 return acpi_video_bus_DOS(video, 0,
1524 acpi_video_backlight_quirks() ? 1 : 0); 1412 acpi_osi_is_win8() ? 1 : 0);
1525} 1413}
1526 1414
1527static int acpi_video_bus_stop_devices(struct acpi_video_bus *video) 1415static int acpi_video_bus_stop_devices(struct acpi_video_bus *video)
1528{ 1416{
1529 return acpi_video_bus_DOS(video, 0, 1417 return acpi_video_bus_DOS(video, 0,
1530 acpi_video_backlight_quirks() ? 0 : 1); 1418 acpi_osi_is_win8() ? 0 : 1);
1531} 1419}
1532 1420
1533static void acpi_video_bus_notify(struct acpi_device *device, u32 event) 1421static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
@@ -1536,7 +1424,7 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
1536 struct input_dev *input; 1424 struct input_dev *input;
1537 int keycode = 0; 1425 int keycode = 0;
1538 1426
1539 if (!video) 1427 if (!video || !video->input)
1540 return; 1428 return;
1541 1429
1542 input = video->input; 1430 input = video->input;
@@ -1691,12 +1579,236 @@ acpi_video_bus_match(acpi_handle handle, u32 level, void *context,
1691 return AE_OK; 1579 return AE_OK;
1692} 1580}
1693 1581
1582static void acpi_video_dev_register_backlight(struct acpi_video_device *device)
1583{
1584 if (acpi_video_verify_backlight_support()) {
1585 struct backlight_properties props;
1586 struct pci_dev *pdev;
1587 acpi_handle acpi_parent;
1588 struct device *parent = NULL;
1589 int result;
1590 static int count;
1591 char *name;
1592
1593 result = acpi_video_init_brightness(device);
1594 if (result)
1595 return;
1596 name = kasprintf(GFP_KERNEL, "acpi_video%d", count);
1597 if (!name)
1598 return;
1599 count++;
1600
1601 acpi_get_parent(device->dev->handle, &acpi_parent);
1602
1603 pdev = acpi_get_pci_dev(acpi_parent);
1604 if (pdev) {
1605 parent = &pdev->dev;
1606 pci_dev_put(pdev);
1607 }
1608
1609 memset(&props, 0, sizeof(struct backlight_properties));
1610 props.type = BACKLIGHT_FIRMWARE;
1611 props.max_brightness = device->brightness->count - 3;
1612 device->backlight = backlight_device_register(name,
1613 parent,
1614 device,
1615 &acpi_backlight_ops,
1616 &props);
1617 kfree(name);
1618 if (IS_ERR(device->backlight))
1619 return;
1620
1621 /*
1622 * Save current brightness level in case we have to restore it
1623 * before acpi_video_device_lcd_set_level() is called next time.
1624 */
1625 device->backlight->props.brightness =
1626 acpi_video_get_brightness(device->backlight);
1627
1628 device->cooling_dev = thermal_cooling_device_register("LCD",
1629 device->dev, &video_cooling_ops);
1630 if (IS_ERR(device->cooling_dev)) {
1631 /*
1632 * Set cooling_dev to NULL so we don't crash trying to
1633 * free it.
1634 * Also, why the hell we are returning early and
1635 * not attempt to register video output if cooling
1636 * device registration failed?
1637 * -- dtor
1638 */
1639 device->cooling_dev = NULL;
1640 return;
1641 }
1642
1643 dev_info(&device->dev->dev, "registered as cooling_device%d\n",
1644 device->cooling_dev->id);
1645 result = sysfs_create_link(&device->dev->dev.kobj,
1646 &device->cooling_dev->device.kobj,
1647 "thermal_cooling");
1648 if (result)
1649 printk(KERN_ERR PREFIX "Create sysfs link\n");
1650 result = sysfs_create_link(&device->cooling_dev->device.kobj,
1651 &device->dev->dev.kobj, "device");
1652 if (result)
1653 printk(KERN_ERR PREFIX "Create sysfs link\n");
1654 }
1655}
1656
1657static int acpi_video_bus_register_backlight(struct acpi_video_bus *video)
1658{
1659 struct acpi_video_device *dev;
1660
1661 mutex_lock(&video->device_list_lock);
1662 list_for_each_entry(dev, &video->video_device_list, entry)
1663 acpi_video_dev_register_backlight(dev);
1664 mutex_unlock(&video->device_list_lock);
1665
1666 video->pm_nb.notifier_call = acpi_video_resume;
1667 video->pm_nb.priority = 0;
1668 return register_pm_notifier(&video->pm_nb);
1669}
1670
1671static void acpi_video_dev_unregister_backlight(struct acpi_video_device *device)
1672{
1673 if (device->backlight) {
1674 backlight_device_unregister(device->backlight);
1675 device->backlight = NULL;
1676 }
1677 if (device->brightness) {
1678 kfree(device->brightness->levels);
1679 kfree(device->brightness);
1680 device->brightness = NULL;
1681 }
1682 if (device->cooling_dev) {
1683 sysfs_remove_link(&device->dev->dev.kobj, "thermal_cooling");
1684 sysfs_remove_link(&device->cooling_dev->device.kobj, "device");
1685 thermal_cooling_device_unregister(device->cooling_dev);
1686 device->cooling_dev = NULL;
1687 }
1688}
1689
1690static int acpi_video_bus_unregister_backlight(struct acpi_video_bus *video)
1691{
1692 struct acpi_video_device *dev;
1693 int error = unregister_pm_notifier(&video->pm_nb);
1694
1695 mutex_lock(&video->device_list_lock);
1696 list_for_each_entry(dev, &video->video_device_list, entry)
1697 acpi_video_dev_unregister_backlight(dev);
1698 mutex_unlock(&video->device_list_lock);
1699
1700 return error;
1701}
1702
1703static void acpi_video_dev_add_notify_handler(struct acpi_video_device *device)
1704{
1705 acpi_status status;
1706 struct acpi_device *adev = device->dev;
1707
1708 status = acpi_install_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY,
1709 acpi_video_device_notify, device);
1710 if (ACPI_FAILURE(status))
1711 dev_err(&adev->dev, "Error installing notify handler\n");
1712 else
1713 device->flags.notify = 1;
1714}
1715
1716static int acpi_video_bus_add_notify_handler(struct acpi_video_bus *video)
1717{
1718 struct input_dev *input;
1719 struct acpi_video_device *dev;
1720 int error;
1721
1722 video->input = input = input_allocate_device();
1723 if (!input) {
1724 error = -ENOMEM;
1725 goto out;
1726 }
1727
1728 error = acpi_video_bus_start_devices(video);
1729 if (error)
1730 goto err_free_input;
1731
1732 snprintf(video->phys, sizeof(video->phys),
1733 "%s/video/input0", acpi_device_hid(video->device));
1734
1735 input->name = acpi_device_name(video->device);
1736 input->phys = video->phys;
1737 input->id.bustype = BUS_HOST;
1738 input->id.product = 0x06;
1739 input->dev.parent = &video->device->dev;
1740 input->evbit[0] = BIT(EV_KEY);
1741 set_bit(KEY_SWITCHVIDEOMODE, input->keybit);
1742 set_bit(KEY_VIDEO_NEXT, input->keybit);
1743 set_bit(KEY_VIDEO_PREV, input->keybit);
1744 set_bit(KEY_BRIGHTNESS_CYCLE, input->keybit);
1745 set_bit(KEY_BRIGHTNESSUP, input->keybit);
1746 set_bit(KEY_BRIGHTNESSDOWN, input->keybit);
1747 set_bit(KEY_BRIGHTNESS_ZERO, input->keybit);
1748 set_bit(KEY_DISPLAY_OFF, input->keybit);
1749
1750 error = input_register_device(input);
1751 if (error)
1752 goto err_stop_dev;
1753
1754 mutex_lock(&video->device_list_lock);
1755 list_for_each_entry(dev, &video->video_device_list, entry)
1756 acpi_video_dev_add_notify_handler(dev);
1757 mutex_unlock(&video->device_list_lock);
1758
1759 return 0;
1760
1761err_stop_dev:
1762 acpi_video_bus_stop_devices(video);
1763err_free_input:
1764 input_free_device(input);
1765 video->input = NULL;
1766out:
1767 return error;
1768}
1769
1770static void acpi_video_dev_remove_notify_handler(struct acpi_video_device *dev)
1771{
1772 if (dev->flags.notify) {
1773 acpi_remove_notify_handler(dev->dev->handle, ACPI_DEVICE_NOTIFY,
1774 acpi_video_device_notify);
1775 dev->flags.notify = 0;
1776 }
1777}
1778
1779static void acpi_video_bus_remove_notify_handler(struct acpi_video_bus *video)
1780{
1781 struct acpi_video_device *dev;
1782
1783 mutex_lock(&video->device_list_lock);
1784 list_for_each_entry(dev, &video->video_device_list, entry)
1785 acpi_video_dev_remove_notify_handler(dev);
1786 mutex_unlock(&video->device_list_lock);
1787
1788 acpi_video_bus_stop_devices(video);
1789 input_unregister_device(video->input);
1790 video->input = NULL;
1791}
1792
1793static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
1794{
1795 struct acpi_video_device *dev, *next;
1796
1797 mutex_lock(&video->device_list_lock);
1798 list_for_each_entry_safe(dev, next, &video->video_device_list, entry) {
1799 list_del(&dev->entry);
1800 kfree(dev);
1801 }
1802 mutex_unlock(&video->device_list_lock);
1803
1804 return 0;
1805}
1806
1694static int instance; 1807static int instance;
1695 1808
1696static int acpi_video_bus_add(struct acpi_device *device) 1809static int acpi_video_bus_add(struct acpi_device *device)
1697{ 1810{
1698 struct acpi_video_bus *video; 1811 struct acpi_video_bus *video;
1699 struct input_dev *input;
1700 int error; 1812 int error;
1701 acpi_status status; 1813 acpi_status status;
1702 1814
@@ -1748,62 +1860,24 @@ static int acpi_video_bus_add(struct acpi_device *device)
1748 if (error) 1860 if (error)
1749 goto err_put_video; 1861 goto err_put_video;
1750 1862
1751 video->input = input = input_allocate_device();
1752 if (!input) {
1753 error = -ENOMEM;
1754 goto err_put_video;
1755 }
1756
1757 error = acpi_video_bus_start_devices(video);
1758 if (error)
1759 goto err_free_input_dev;
1760
1761 snprintf(video->phys, sizeof(video->phys),
1762 "%s/video/input0", acpi_device_hid(video->device));
1763
1764 input->name = acpi_device_name(video->device);
1765 input->phys = video->phys;
1766 input->id.bustype = BUS_HOST;
1767 input->id.product = 0x06;
1768 input->dev.parent = &device->dev;
1769 input->evbit[0] = BIT(EV_KEY);
1770 set_bit(KEY_SWITCHVIDEOMODE, input->keybit);
1771 set_bit(KEY_VIDEO_NEXT, input->keybit);
1772 set_bit(KEY_VIDEO_PREV, input->keybit);
1773 set_bit(KEY_BRIGHTNESS_CYCLE, input->keybit);
1774 set_bit(KEY_BRIGHTNESSUP, input->keybit);
1775 set_bit(KEY_BRIGHTNESSDOWN, input->keybit);
1776 set_bit(KEY_BRIGHTNESS_ZERO, input->keybit);
1777 set_bit(KEY_DISPLAY_OFF, input->keybit);
1778
1779 printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", 1863 printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n",
1780 ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), 1864 ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
1781 video->flags.multihead ? "yes" : "no", 1865 video->flags.multihead ? "yes" : "no",
1782 video->flags.rom ? "yes" : "no", 1866 video->flags.rom ? "yes" : "no",
1783 video->flags.post ? "yes" : "no"); 1867 video->flags.post ? "yes" : "no");
1868 mutex_lock(&video_list_lock);
1869 list_add_tail(&video->entry, &video_bus_head);
1870 mutex_unlock(&video_list_lock);
1784 1871
1785 video->pm_nb.notifier_call = acpi_video_resume; 1872 acpi_video_bus_register_backlight(video);
1786 video->pm_nb.priority = 0; 1873 acpi_video_bus_add_notify_handler(video);
1787 error = register_pm_notifier(&video->pm_nb);
1788 if (error)
1789 goto err_stop_video;
1790
1791 error = input_register_device(input);
1792 if (error)
1793 goto err_unregister_pm_notifier;
1794 1874
1795 return 0; 1875 return 0;
1796 1876
1797 err_unregister_pm_notifier: 1877err_put_video:
1798 unregister_pm_notifier(&video->pm_nb);
1799 err_stop_video:
1800 acpi_video_bus_stop_devices(video);
1801 err_free_input_dev:
1802 input_free_device(input);
1803 err_put_video:
1804 acpi_video_bus_put_devices(video); 1878 acpi_video_bus_put_devices(video);
1805 kfree(video->attached_array); 1879 kfree(video->attached_array);
1806 err_free_video: 1880err_free_video:
1807 kfree(video); 1881 kfree(video);
1808 device->driver_data = NULL; 1882 device->driver_data = NULL;
1809 1883
@@ -1820,12 +1894,14 @@ static int acpi_video_bus_remove(struct acpi_device *device)
1820 1894
1821 video = acpi_driver_data(device); 1895 video = acpi_driver_data(device);
1822 1896
1823 unregister_pm_notifier(&video->pm_nb); 1897 acpi_video_bus_remove_notify_handler(video);
1824 1898 acpi_video_bus_unregister_backlight(video);
1825 acpi_video_bus_stop_devices(video);
1826 acpi_video_bus_put_devices(video); 1899 acpi_video_bus_put_devices(video);
1827 1900
1828 input_unregister_device(video->input); 1901 mutex_lock(&video_list_lock);
1902 list_del(&video->entry);
1903 mutex_unlock(&video_list_lock);
1904
1829 kfree(video->attached_array); 1905 kfree(video->attached_array);
1830 kfree(video); 1906 kfree(video);
1831 1907
@@ -1874,6 +1950,9 @@ int acpi_video_register(void)
1874 return 0; 1950 return 0;
1875 } 1951 }
1876 1952
1953 mutex_init(&video_list_lock);
1954 INIT_LIST_HEAD(&video_bus_head);
1955
1877 result = acpi_bus_register_driver(&acpi_video_bus); 1956 result = acpi_bus_register_driver(&acpi_video_bus);
1878 if (result < 0) 1957 if (result < 0)
1879 return -ENODEV; 1958 return -ENODEV;
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index 940edbf2fe8f..84875fd4c74f 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -168,6 +168,14 @@ static struct dmi_system_id video_detect_dmi_table[] = {
168 DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"), 168 DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"),
169 }, 169 },
170 }, 170 },
171 {
172 .callback = video_detect_force_vendor,
173 .ident = "Lenovo Yoga 13",
174 .matches = {
175 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
176 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga 13"),
177 },
178 },
171 { }, 179 { },
172}; 180};
173 181
@@ -233,11 +241,11 @@ static void acpi_video_caps_check(void)
233 acpi_video_get_capabilities(NULL); 241 acpi_video_get_capabilities(NULL);
234} 242}
235 243
236bool acpi_video_backlight_quirks(void) 244bool acpi_osi_is_win8(void)
237{ 245{
238 return acpi_gbl_osi_data >= ACPI_OSI_WIN_8; 246 return acpi_gbl_osi_data >= ACPI_OSI_WIN_8;
239} 247}
240EXPORT_SYMBOL(acpi_video_backlight_quirks); 248EXPORT_SYMBOL(acpi_osi_is_win8);
241 249
242/* Promote the vendor interface instead of the generic video module. 250/* Promote the vendor interface instead of the generic video module.
243 * This function allow DMI blacklists to be implemented by externals 251 * This function allow DMI blacklists to be implemented by externals
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 03ca6c139f1a..170f2788ee67 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -700,6 +700,14 @@ static void __init drv_acpi_handle_init(const char *name,
700static acpi_status __init tpacpi_acpi_handle_locate_callback(acpi_handle handle, 700static acpi_status __init tpacpi_acpi_handle_locate_callback(acpi_handle handle,
701 u32 level, void *context, void **return_value) 701 u32 level, void *context, void **return_value)
702{ 702{
703 struct acpi_device *dev;
704 if (!strcmp(context, "video")) {
705 if (acpi_bus_get_device(handle, &dev))
706 return AE_OK;
707 if (strcmp(ACPI_VIDEO_HID, acpi_device_hid(dev)))
708 return AE_OK;
709 }
710
703 *(acpi_handle *)return_value = handle; 711 *(acpi_handle *)return_value = handle;
704 712
705 return AE_CTRL_TERMINATE; 713 return AE_CTRL_TERMINATE;
@@ -712,10 +720,10 @@ static void __init tpacpi_acpi_handle_locate(const char *name,
712 acpi_status status; 720 acpi_status status;
713 acpi_handle device_found; 721 acpi_handle device_found;
714 722
715 BUG_ON(!name || !hid || !handle); 723 BUG_ON(!name || !handle);
716 vdbg_printk(TPACPI_DBG_INIT, 724 vdbg_printk(TPACPI_DBG_INIT,
717 "trying to locate ACPI handle for %s, using HID %s\n", 725 "trying to locate ACPI handle for %s, using HID %s\n",
718 name, hid); 726 name, hid ? hid : "NULL");
719 727
720 memset(&device_found, 0, sizeof(device_found)); 728 memset(&device_found, 0, sizeof(device_found));
721 status = acpi_get_devices(hid, tpacpi_acpi_handle_locate_callback, 729 status = acpi_get_devices(hid, tpacpi_acpi_handle_locate_callback,
@@ -6090,19 +6098,28 @@ static int __init tpacpi_query_bcl_levels(acpi_handle handle)
6090{ 6098{
6091 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 6099 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
6092 union acpi_object *obj; 6100 union acpi_object *obj;
6101 struct acpi_device *device, *child;
6093 int rc; 6102 int rc;
6094 6103
6095 if (ACPI_SUCCESS(acpi_evaluate_object(handle, "_BCL", NULL, &buffer))) { 6104 if (acpi_bus_get_device(handle, &device))
6105 return 0;
6106
6107 rc = 0;
6108 list_for_each_entry(child, &device->children, node) {
6109 acpi_status status = acpi_evaluate_object(child->handle, "_BCL",
6110 NULL, &buffer);
6111 if (ACPI_FAILURE(status))
6112 continue;
6113
6096 obj = (union acpi_object *)buffer.pointer; 6114 obj = (union acpi_object *)buffer.pointer;
6097 if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { 6115 if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
6098 pr_err("Unknown _BCL data, please report this to %s\n", 6116 pr_err("Unknown _BCL data, please report this to %s\n",
6099 TPACPI_MAIL); 6117 TPACPI_MAIL);
6100 rc = 0; 6118 rc = 0;
6101 } else { 6119 } else {
6102 rc = obj->package.count; 6120 rc = obj->package.count;
6103 } 6121 }
6104 } else { 6122 break;
6105 return 0;
6106 } 6123 }
6107 6124
6108 kfree(buffer.pointer); 6125 kfree(buffer.pointer);
@@ -6118,7 +6135,7 @@ static unsigned int __init tpacpi_check_std_acpi_brightness_support(void)
6118 acpi_handle video_device; 6135 acpi_handle video_device;
6119 int bcl_levels = 0; 6136 int bcl_levels = 0;
6120 6137
6121 tpacpi_acpi_handle_locate("video", ACPI_VIDEO_HID, &video_device); 6138 tpacpi_acpi_handle_locate("video", NULL, &video_device);
6122 if (video_device) 6139 if (video_device)
6123 bcl_levels = tpacpi_query_bcl_levels(video_device); 6140 bcl_levels = tpacpi_query_bcl_levels(video_device);
6124 6141
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 94a403a9717a..5d05555fe841 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -21,6 +21,9 @@
21#include <asm/backlight.h> 21#include <asm/backlight.h>
22#endif 22#endif
23 23
24static struct list_head backlight_dev_list;
25static struct mutex backlight_dev_list_mutex;
26
24static const char *const backlight_types[] = { 27static const char *const backlight_types[] = {
25 [BACKLIGHT_RAW] = "raw", 28 [BACKLIGHT_RAW] = "raw",
26 [BACKLIGHT_PLATFORM] = "platform", 29 [BACKLIGHT_PLATFORM] = "platform",
@@ -349,10 +352,32 @@ struct backlight_device *backlight_device_register(const char *name,
349 mutex_unlock(&pmac_backlight_mutex); 352 mutex_unlock(&pmac_backlight_mutex);
350#endif 353#endif
351 354
355 mutex_lock(&backlight_dev_list_mutex);
356 list_add(&new_bd->entry, &backlight_dev_list);
357 mutex_unlock(&backlight_dev_list_mutex);
358
352 return new_bd; 359 return new_bd;
353} 360}
354EXPORT_SYMBOL(backlight_device_register); 361EXPORT_SYMBOL(backlight_device_register);
355 362
363bool backlight_device_registered(enum backlight_type type)
364{
365 bool found = false;
366 struct backlight_device *bd;
367
368 mutex_lock(&backlight_dev_list_mutex);
369 list_for_each_entry(bd, &backlight_dev_list, entry) {
370 if (bd->props.type == type) {
371 found = true;
372 break;
373 }
374 }
375 mutex_unlock(&backlight_dev_list_mutex);
376
377 return found;
378}
379EXPORT_SYMBOL(backlight_device_registered);
380
356/** 381/**
357 * backlight_device_unregister - unregisters a backlight device object. 382 * backlight_device_unregister - unregisters a backlight device object.
358 * @bd: the backlight device object to be unregistered and freed. 383 * @bd: the backlight device object to be unregistered and freed.
@@ -364,6 +389,10 @@ void backlight_device_unregister(struct backlight_device *bd)
364 if (!bd) 389 if (!bd)
365 return; 390 return;
366 391
392 mutex_lock(&backlight_dev_list_mutex);
393 list_del(&bd->entry);
394 mutex_unlock(&backlight_dev_list_mutex);
395
367#ifdef CONFIG_PMAC_BACKLIGHT 396#ifdef CONFIG_PMAC_BACKLIGHT
368 mutex_lock(&pmac_backlight_mutex); 397 mutex_lock(&pmac_backlight_mutex);
369 if (pmac_backlight == bd) 398 if (pmac_backlight == bd)
@@ -499,6 +528,8 @@ static int __init backlight_class_init(void)
499 528
500 backlight_class->dev_groups = bl_device_groups; 529 backlight_class->dev_groups = bl_device_groups;
501 backlight_class->pm = &backlight_class_dev_pm_ops; 530 backlight_class->pm = &backlight_class_dev_pm_ops;
531 INIT_LIST_HEAD(&backlight_dev_list);
532 mutex_init(&backlight_dev_list_mutex);
502 return 0; 533 return 0;
503} 534}
504 535
diff --git a/include/linux/backlight.h b/include/linux/backlight.h
index 53b77949c79d..5f9cd963213d 100644
--- a/include/linux/backlight.h
+++ b/include/linux/backlight.h
@@ -100,6 +100,9 @@ struct backlight_device {
100 /* The framebuffer notifier block */ 100 /* The framebuffer notifier block */
101 struct notifier_block fb_notif; 101 struct notifier_block fb_notif;
102 102
103 /* list entry of all registered backlight devices */
104 struct list_head entry;
105
103 struct device dev; 106 struct device dev;
104}; 107};
105 108
@@ -123,6 +126,7 @@ extern void devm_backlight_device_unregister(struct device *dev,
123 struct backlight_device *bd); 126 struct backlight_device *bd);
124extern void backlight_force_update(struct backlight_device *bd, 127extern void backlight_force_update(struct backlight_device *bd,
125 enum backlight_update_reason reason); 128 enum backlight_update_reason reason);
129extern bool backlight_device_registered(enum backlight_type type);
126 130
127#define to_backlight_device(obj) container_of(obj, struct backlight_device, dev) 131#define to_backlight_device(obj) container_of(obj, struct backlight_device, dev)
128 132