Commit 7751ab8e600f26e10c2ba12a92d48a4852a51da8
Committed by
Matthew Garrett
1 parent
bf15571401
Exists in
master
and in
4 other branches
sony-laptop: implement new backlight control method
Reasonably recent Vaios have a 0x12f or 0x137 handler that exposes a fine lid backlight regulation with values ranging from 0 to 255. The patch is based on findings and code from Javier Achirica <achirica@gmail.com> and Marco Chiappero <marco@absence.it> Signed-off-by: Mattia Dongili <malattia@linux.it> Signed-off-by: Matthew Garrett <mjg@redhat.com>
Showing 1 changed file with 79 additions and 30 deletions Side-by-side Diff
drivers/platform/x86/sony-laptop.c
... | ... | @@ -938,11 +938,39 @@ |
938 | 938 | return value - 1; |
939 | 939 | } |
940 | 940 | |
941 | -static struct backlight_device *sony_backlight_device; | |
941 | +static int sony_nc_get_brightness_ng(struct backlight_device *bd) | |
942 | +{ | |
943 | + int result; | |
944 | + int *handle = (int *)bl_get_data(bd); | |
945 | + | |
946 | + sony_call_snc_handle(*handle, 0x0200, &result); | |
947 | + | |
948 | + return result & 0xff; | |
949 | +} | |
950 | + | |
951 | +static int sony_nc_update_status_ng(struct backlight_device *bd) | |
952 | +{ | |
953 | + int value, result; | |
954 | + int *handle = (int *)bl_get_data(bd); | |
955 | + | |
956 | + value = bd->props.brightness; | |
957 | + sony_call_snc_handle(*handle, 0x0100 | (value << 16), &result); | |
958 | + | |
959 | + return sony_nc_get_brightness_ng(bd); | |
960 | +} | |
961 | + | |
942 | 962 | static const struct backlight_ops sony_backlight_ops = { |
963 | + .options = BL_CORE_SUSPENDRESUME, | |
943 | 964 | .update_status = sony_backlight_update_status, |
944 | 965 | .get_brightness = sony_backlight_get_brightness, |
945 | 966 | }; |
967 | +static const struct backlight_ops sony_backlight_ng_ops = { | |
968 | + .options = BL_CORE_SUSPENDRESUME, | |
969 | + .update_status = sony_nc_update_status_ng, | |
970 | + .get_brightness = sony_nc_get_brightness_ng, | |
971 | +}; | |
972 | +static int backlight_ng_handle; | |
973 | +static struct backlight_device *sony_backlight_device; | |
946 | 974 | |
947 | 975 | /* |
948 | 976 | * New SNC-only Vaios event mapping to driver known keys |
... | ... | @@ -1135,11 +1163,6 @@ |
1135 | 1163 | sony_nc_function_setup(device); |
1136 | 1164 | } |
1137 | 1165 | |
1138 | - /* set the last requested brightness level */ | |
1139 | - if (sony_backlight_device && | |
1140 | - sony_backlight_update_status(sony_backlight_device) < 0) | |
1141 | - pr_warn(DRV_PFX "unable to restore brightness level\n"); | |
1142 | - | |
1143 | 1166 | /* re-read rfkill state */ |
1144 | 1167 | sony_nc_rfkill_update(); |
1145 | 1168 | |
... | ... | @@ -1477,6 +1500,52 @@ |
1477 | 1500 | return 0; |
1478 | 1501 | } |
1479 | 1502 | |
1503 | +static void sony_nc_backlight_setup(void) | |
1504 | +{ | |
1505 | + acpi_handle unused; | |
1506 | + int max_brightness = 0; | |
1507 | + const struct backlight_ops *ops = NULL; | |
1508 | + struct backlight_properties props; | |
1509 | + | |
1510 | + if (sony_find_snc_handle(0x12f) != -1) { | |
1511 | + backlight_ng_handle = 0x12f; | |
1512 | + ops = &sony_backlight_ng_ops; | |
1513 | + max_brightness = 0xff; | |
1514 | + | |
1515 | + } else if (sony_find_snc_handle(0x137) != -1) { | |
1516 | + backlight_ng_handle = 0x137; | |
1517 | + ops = &sony_backlight_ng_ops; | |
1518 | + max_brightness = 0xff; | |
1519 | + | |
1520 | + } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", | |
1521 | + &unused))) { | |
1522 | + ops = &sony_backlight_ops; | |
1523 | + max_brightness = SONY_MAX_BRIGHTNESS - 1; | |
1524 | + | |
1525 | + } else | |
1526 | + return; | |
1527 | + | |
1528 | + memset(&props, 0, sizeof(struct backlight_properties)); | |
1529 | + props.type = BACKLIGHT_PLATFORM; | |
1530 | + props.max_brightness = max_brightness; | |
1531 | + sony_backlight_device = backlight_device_register("sony", NULL, | |
1532 | + &backlight_ng_handle, | |
1533 | + ops, &props); | |
1534 | + | |
1535 | + if (IS_ERR(sony_backlight_device)) { | |
1536 | + pr_warning(DRV_PFX "unable to register backlight device\n"); | |
1537 | + sony_backlight_device = NULL; | |
1538 | + } else | |
1539 | + sony_backlight_device->props.brightness = | |
1540 | + ops->get_brightness(sony_backlight_device); | |
1541 | +} | |
1542 | + | |
1543 | +static void sony_nc_backlight_cleanup(void) | |
1544 | +{ | |
1545 | + if (sony_backlight_device) | |
1546 | + backlight_device_unregister(sony_backlight_device); | |
1547 | +} | |
1548 | + | |
1480 | 1549 | static int sony_nc_add(struct acpi_device *device) |
1481 | 1550 | { |
1482 | 1551 | acpi_status status; |
... | ... | @@ -1543,26 +1612,8 @@ |
1543 | 1612 | if (acpi_video_backlight_support()) { |
1544 | 1613 | pr_info(DRV_PFX "brightness ignored, must be " |
1545 | 1614 | "controlled by ACPI video driver\n"); |
1546 | - } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", | |
1547 | - &handle))) { | |
1548 | - struct backlight_properties props; | |
1549 | - memset(&props, 0, sizeof(struct backlight_properties)); | |
1550 | - props.type = BACKLIGHT_PLATFORM; | |
1551 | - props.max_brightness = SONY_MAX_BRIGHTNESS - 1; | |
1552 | - sony_backlight_device = backlight_device_register("sony", NULL, | |
1553 | - NULL, | |
1554 | - &sony_backlight_ops, | |
1555 | - &props); | |
1556 | - | |
1557 | - if (IS_ERR(sony_backlight_device)) { | |
1558 | - pr_warning(DRV_PFX "unable to register backlight device\n"); | |
1559 | - sony_backlight_device = NULL; | |
1560 | - } else { | |
1561 | - sony_backlight_device->props.brightness = | |
1562 | - sony_backlight_get_brightness | |
1563 | - (sony_backlight_device); | |
1564 | - } | |
1565 | - | |
1615 | + } else { | |
1616 | + sony_nc_backlight_setup(); | |
1566 | 1617 | } |
1567 | 1618 | |
1568 | 1619 | /* create sony_pf sysfs attributes related to the SNC device */ |
... | ... | @@ -1610,8 +1661,7 @@ |
1610 | 1661 | for (item = sony_nc_values; item->name; ++item) { |
1611 | 1662 | device_remove_file(&sony_pf_device->dev, &item->devattr); |
1612 | 1663 | } |
1613 | - if (sony_backlight_device) | |
1614 | - backlight_device_unregister(sony_backlight_device); | |
1664 | + sony_nc_backlight_cleanup(); | |
1615 | 1665 | |
1616 | 1666 | sony_laptop_remove_input(); |
1617 | 1667 | |
... | ... | @@ -1633,8 +1683,7 @@ |
1633 | 1683 | { |
1634 | 1684 | struct sony_nc_value *item; |
1635 | 1685 | |
1636 | - if (sony_backlight_device) | |
1637 | - backlight_device_unregister(sony_backlight_device); | |
1686 | + sony_nc_backlight_cleanup(); | |
1638 | 1687 | |
1639 | 1688 | sony_nc_acpi_device = NULL; |
1640 | 1689 |