diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-10-27 20:20:14 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-10-27 20:20:14 -0400 |
commit | 975bcabb05436d8b99214a2293d1d5b9c0b0ca08 (patch) | |
tree | a3c1049d5029ed6726ec4135ca18b4d9595d2b55 | |
parent | dd6c26be3bb3e98d4811780f831bbc246dae54c8 (diff) | |
parent | 1bdb71af7f1388fd4b305134035008a81f2032b8 (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.c | 61 | ||||
-rw-r--r-- | drivers/acpi/internal.h | 4 | ||||
-rw-r--r-- | drivers/acpi/video.c | 465 | ||||
-rw-r--r-- | drivers/acpi/video_detect.c | 12 | ||||
-rw-r--r-- | drivers/platform/x86/thinkpad_acpi.c | 31 | ||||
-rw-r--r-- | drivers/video/backlight/backlight.c | 31 | ||||
-rw-r--r-- | include/linux/backlight.h | 4 |
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) |
172 | bool acpi_video_backlight_quirks(void); | 172 | bool acpi_osi_is_win8(void); |
173 | #else | ||
174 | static 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); | |||
88 | static bool use_bios_initial_backlight = 1; | 88 | static bool use_bios_initial_backlight = 1; |
89 | module_param(use_bios_initial_backlight, bool, 0644); | 89 | module_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 | */ | ||
95 | static bool use_native_backlight = false; | ||
96 | module_param(use_native_backlight, bool, 0644); | ||
97 | |||
91 | static int register_count; | 98 | static int register_count; |
99 | static struct mutex video_list_lock; | ||
100 | static struct list_head video_bus_head; | ||
92 | static int acpi_video_bus_add(struct acpi_device *device); | 101 | static int acpi_video_bus_add(struct acpi_device *device); |
93 | static int acpi_video_bus_remove(struct acpi_device *device); | 102 | static int acpi_video_bus_remove(struct acpi_device *device); |
94 | static void acpi_video_bus_notify(struct acpi_device *device, u32 event); | 103 | static 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, | |||
229 | static int acpi_video_switch_brightness(struct acpi_video_device *device, | 239 | static int acpi_video_switch_brightness(struct acpi_video_device *device, |
230 | int event); | 240 | int event); |
231 | 241 | ||
242 | static 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 */ |
233 | static int acpi_video_get_brightness(struct backlight_device *bd) | 251 | static 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 | ||
1457 | static 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 | |||
1488 | static 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) | |||
1521 | static int acpi_video_bus_start_devices(struct acpi_video_bus *video) | 1409 | static 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 | ||
1527 | static int acpi_video_bus_stop_devices(struct acpi_video_bus *video) | 1415 | static 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 | ||
1533 | static void acpi_video_bus_notify(struct acpi_device *device, u32 event) | 1421 | static 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 | ||
1582 | static 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 | |||
1657 | static 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 | |||
1671 | static 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 | |||
1690 | static 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 | |||
1703 | static 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 | |||
1716 | static 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 | |||
1761 | err_stop_dev: | ||
1762 | acpi_video_bus_stop_devices(video); | ||
1763 | err_free_input: | ||
1764 | input_free_device(input); | ||
1765 | video->input = NULL; | ||
1766 | out: | ||
1767 | return error; | ||
1768 | } | ||
1769 | |||
1770 | static 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 | |||
1779 | static 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 | |||
1793 | static 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 | |||
1694 | static int instance; | 1807 | static int instance; |
1695 | 1808 | ||
1696 | static int acpi_video_bus_add(struct acpi_device *device) | 1809 | static 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: | 1877 | err_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: | 1880 | err_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 | ||
236 | bool acpi_video_backlight_quirks(void) | 244 | bool 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 | } |
240 | EXPORT_SYMBOL(acpi_video_backlight_quirks); | 248 | EXPORT_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, | |||
700 | static acpi_status __init tpacpi_acpi_handle_locate_callback(acpi_handle handle, | 700 | static 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 | ||
24 | static struct list_head backlight_dev_list; | ||
25 | static struct mutex backlight_dev_list_mutex; | ||
26 | |||
24 | static const char *const backlight_types[] = { | 27 | static 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 | } |
354 | EXPORT_SYMBOL(backlight_device_register); | 361 | EXPORT_SYMBOL(backlight_device_register); |
355 | 362 | ||
363 | bool 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 | } | ||
379 | EXPORT_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); |
124 | extern void backlight_force_update(struct backlight_device *bd, | 127 | extern void backlight_force_update(struct backlight_device *bd, |
125 | enum backlight_update_reason reason); | 128 | enum backlight_update_reason reason); |
129 | extern 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 | ||