diff options
author | Marco Chiappero <marco@absence.it> | 2012-05-19 09:35:56 -0400 |
---|---|---|
committer | Matthew Garrett <mjg@redhat.com> | 2012-05-31 14:34:42 -0400 |
commit | aa33924f35842cc7544865fd13713d1bb88aee65 (patch) | |
tree | ceb4da83e5b20b4e5d6d4ee2aa5297af9edbeeb4 /drivers/platform/x86 | |
parent | 88bf170646c3673877f4449127c2940c0bc307ca (diff) |
sony-laptop: new keyboard backlight handle
Add support for handle 0x0143 (Vaio SA/SB/SC, CA/CB) and rework the code
to be hable to support different handles for the keyboard backlight
function.
[malattia@linux.it: group function specific variables in a struct]
Signed-off-by: Marco Chiappero <marco@absence.it>
Signed-off-by: Mattia Dongili <malattia@linux.it>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers/platform/x86')
-rw-r--r-- | drivers/platform/x86/sony-laptop.c | 149 |
1 files changed, 87 insertions, 62 deletions
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index fcbedc972021..e0bc418bd22d 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c | |||
@@ -141,8 +141,9 @@ MODULE_PARM_DESC(kbd_backlight_timeout, | |||
141 | "(default: 0)"); | 141 | "(default: 0)"); |
142 | 142 | ||
143 | static void sony_nc_kbd_backlight_resume(void); | 143 | static void sony_nc_kbd_backlight_resume(void); |
144 | static void sony_nc_kbd_backlight_setup(struct platform_device *pd); | 144 | static int sony_nc_kbd_backlight_setup(struct platform_device *pd, |
145 | static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd); | 145 | unsigned int handle); |
146 | static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd); | ||
146 | 147 | ||
147 | static int sony_nc_battery_care_setup(struct platform_device *pd, | 148 | static int sony_nc_battery_care_setup(struct platform_device *pd, |
148 | unsigned int handle); | 149 | unsigned int handle); |
@@ -1315,7 +1316,11 @@ static void sony_nc_function_setup(struct acpi_device *device, | |||
1315 | sony_nc_rfkill_setup(device); | 1316 | sony_nc_rfkill_setup(device); |
1316 | break; | 1317 | break; |
1317 | case 0x0137: | 1318 | case 0x0137: |
1318 | sony_nc_kbd_backlight_setup(pf_device); | 1319 | case 0x0143: |
1320 | result = sony_nc_kbd_backlight_setup(pf_device, handle); | ||
1321 | if (result) | ||
1322 | pr_err("couldn't set up keyboard backlight function (%d)\n", | ||
1323 | result); | ||
1319 | break; | 1324 | break; |
1320 | default: | 1325 | default: |
1321 | continue; | 1326 | continue; |
@@ -1365,6 +1370,7 @@ static void sony_nc_function_cleanup(struct platform_device *pd) | |||
1365 | sony_nc_rfkill_cleanup(); | 1370 | sony_nc_rfkill_cleanup(); |
1366 | break; | 1371 | break; |
1367 | case 0x0137: | 1372 | case 0x0137: |
1373 | case 0x0143: | ||
1368 | sony_nc_kbd_backlight_cleanup(pd); | 1374 | sony_nc_kbd_backlight_cleanup(pd); |
1369 | break; | 1375 | break; |
1370 | default: | 1376 | default: |
@@ -1407,6 +1413,7 @@ static void sony_nc_function_resume(void) | |||
1407 | sony_nc_rfkill_update(); | 1413 | sony_nc_rfkill_update(); |
1408 | break; | 1414 | break; |
1409 | case 0x0137: | 1415 | case 0x0137: |
1416 | case 0x0143: | ||
1410 | sony_nc_kbd_backlight_resume(); | 1417 | sony_nc_kbd_backlight_resume(); |
1411 | break; | 1418 | break; |
1412 | default: | 1419 | default: |
@@ -1618,20 +1625,16 @@ static void sony_nc_rfkill_setup(struct acpi_device *device) | |||
1618 | } | 1625 | } |
1619 | 1626 | ||
1620 | /* Keyboard backlight feature */ | 1627 | /* Keyboard backlight feature */ |
1621 | #define KBDBL_HANDLER 0x137 | ||
1622 | #define KBDBL_PRESENT 0xB00 | ||
1623 | #define SET_MODE 0xC00 | ||
1624 | #define SET_STATE 0xD00 | ||
1625 | #define SET_TIMEOUT 0xE00 | ||
1626 | |||
1627 | struct kbd_backlight { | 1628 | struct kbd_backlight { |
1628 | int mode; | 1629 | unsigned int handle; |
1629 | int timeout; | 1630 | unsigned int base; |
1631 | unsigned int mode; | ||
1632 | unsigned int timeout; | ||
1630 | struct device_attribute mode_attr; | 1633 | struct device_attribute mode_attr; |
1631 | struct device_attribute timeout_attr; | 1634 | struct device_attribute timeout_attr; |
1632 | }; | 1635 | }; |
1633 | 1636 | ||
1634 | static struct kbd_backlight *kbdbl_handle; | 1637 | static struct kbd_backlight *kbdbl_ctl; |
1635 | 1638 | ||
1636 | static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value) | 1639 | static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value) |
1637 | { | 1640 | { |
@@ -1640,15 +1643,15 @@ static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value) | |||
1640 | if (value > 1) | 1643 | if (value > 1) |
1641 | return -EINVAL; | 1644 | return -EINVAL; |
1642 | 1645 | ||
1643 | if (sony_call_snc_handle(KBDBL_HANDLER, | 1646 | if (sony_call_snc_handle(kbdbl_ctl->handle, |
1644 | (value << 0x10) | SET_MODE, &result)) | 1647 | (value << 0x10) | (kbdbl_ctl->base), &result)) |
1645 | return -EIO; | 1648 | return -EIO; |
1646 | 1649 | ||
1647 | /* Try to turn the light on/off immediately */ | 1650 | /* Try to turn the light on/off immediately */ |
1648 | sony_call_snc_handle(KBDBL_HANDLER, (value << 0x10) | SET_STATE, | 1651 | sony_call_snc_handle(kbdbl_ctl->handle, |
1649 | &result); | 1652 | (value << 0x10) | (kbdbl_ctl->base + 0x100), &result); |
1650 | 1653 | ||
1651 | kbdbl_handle->mode = value; | 1654 | kbdbl_ctl->mode = value; |
1652 | 1655 | ||
1653 | return 0; | 1656 | return 0; |
1654 | } | 1657 | } |
@@ -1677,7 +1680,7 @@ static ssize_t sony_nc_kbd_backlight_mode_show(struct device *dev, | |||
1677 | struct device_attribute *attr, char *buffer) | 1680 | struct device_attribute *attr, char *buffer) |
1678 | { | 1681 | { |
1679 | ssize_t count = 0; | 1682 | ssize_t count = 0; |
1680 | count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->mode); | 1683 | count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_ctl->mode); |
1681 | return count; | 1684 | return count; |
1682 | } | 1685 | } |
1683 | 1686 | ||
@@ -1688,11 +1691,11 @@ static int __sony_nc_kbd_backlight_timeout_set(u8 value) | |||
1688 | if (value > 3) | 1691 | if (value > 3) |
1689 | return -EINVAL; | 1692 | return -EINVAL; |
1690 | 1693 | ||
1691 | if (sony_call_snc_handle(KBDBL_HANDLER, | 1694 | if (sony_call_snc_handle(kbdbl_ctl->handle, (value << 0x10) | |
1692 | (value << 0x10) | SET_TIMEOUT, &result)) | 1695 | (kbdbl_ctl->base + 0x200), &result)) |
1693 | return -EIO; | 1696 | return -EIO; |
1694 | 1697 | ||
1695 | kbdbl_handle->timeout = value; | 1698 | kbdbl_ctl->timeout = value; |
1696 | 1699 | ||
1697 | return 0; | 1700 | return 0; |
1698 | } | 1701 | } |
@@ -1721,85 +1724,107 @@ static ssize_t sony_nc_kbd_backlight_timeout_show(struct device *dev, | |||
1721 | struct device_attribute *attr, char *buffer) | 1724 | struct device_attribute *attr, char *buffer) |
1722 | { | 1725 | { |
1723 | ssize_t count = 0; | 1726 | ssize_t count = 0; |
1724 | count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->timeout); | 1727 | count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_ctl->timeout); |
1725 | return count; | 1728 | return count; |
1726 | } | 1729 | } |
1727 | 1730 | ||
1728 | static void sony_nc_kbd_backlight_setup(struct platform_device *pd) | 1731 | static int sony_nc_kbd_backlight_setup(struct platform_device *pd, |
1732 | unsigned int handle) | ||
1729 | { | 1733 | { |
1730 | int result; | 1734 | int result; |
1735 | int ret = 0; | ||
1731 | 1736 | ||
1732 | if (sony_call_snc_handle(KBDBL_HANDLER, KBDBL_PRESENT, &result)) | 1737 | /* verify the kbd backlight presence, these handles are not used for |
1733 | return; | 1738 | * keyboard backlight only |
1734 | if (!(result & 0x02)) | 1739 | */ |
1735 | return; | 1740 | ret = sony_call_snc_handle(handle, handle == 0x0137 ? 0x0B00 : 0x0100, |
1741 | &result); | ||
1742 | if (ret) | ||
1743 | return ret; | ||
1736 | 1744 | ||
1737 | kbdbl_handle = kzalloc(sizeof(*kbdbl_handle), GFP_KERNEL); | 1745 | if ((handle == 0x0137 && !(result & 0x02)) || |
1738 | if (!kbdbl_handle) | 1746 | !(result & 0x01)) { |
1739 | return; | 1747 | dprintk("no backlight keyboard found\n"); |
1748 | return 0; | ||
1749 | } | ||
1750 | |||
1751 | kbdbl_ctl = kzalloc(sizeof(*kbdbl_ctl), GFP_KERNEL); | ||
1752 | if (!kbdbl_ctl) | ||
1753 | return -ENOMEM; | ||
1754 | |||
1755 | kbdbl_ctl->handle = handle; | ||
1756 | if (handle == 0x0137) | ||
1757 | kbdbl_ctl->base = 0x0C00; | ||
1758 | else | ||
1759 | kbdbl_ctl->base = 0x4000; | ||
1740 | 1760 | ||
1741 | sysfs_attr_init(&kbdbl_handle->mode_attr.attr); | 1761 | sysfs_attr_init(&kbdbl_ctl->mode_attr.attr); |
1742 | kbdbl_handle->mode_attr.attr.name = "kbd_backlight"; | 1762 | kbdbl_ctl->mode_attr.attr.name = "kbd_backlight"; |
1743 | kbdbl_handle->mode_attr.attr.mode = S_IRUGO | S_IWUSR; | 1763 | kbdbl_ctl->mode_attr.attr.mode = S_IRUGO | S_IWUSR; |
1744 | kbdbl_handle->mode_attr.show = sony_nc_kbd_backlight_mode_show; | 1764 | kbdbl_ctl->mode_attr.show = sony_nc_kbd_backlight_mode_show; |
1745 | kbdbl_handle->mode_attr.store = sony_nc_kbd_backlight_mode_store; | 1765 | kbdbl_ctl->mode_attr.store = sony_nc_kbd_backlight_mode_store; |
1746 | 1766 | ||
1747 | sysfs_attr_init(&kbdbl_handle->timeout_attr.attr); | 1767 | sysfs_attr_init(&kbdbl_ctl->timeout_attr.attr); |
1748 | kbdbl_handle->timeout_attr.attr.name = "kbd_backlight_timeout"; | 1768 | kbdbl_ctl->timeout_attr.attr.name = "kbd_backlight_timeout"; |
1749 | kbdbl_handle->timeout_attr.attr.mode = S_IRUGO | S_IWUSR; | 1769 | kbdbl_ctl->timeout_attr.attr.mode = S_IRUGO | S_IWUSR; |
1750 | kbdbl_handle->timeout_attr.show = sony_nc_kbd_backlight_timeout_show; | 1770 | kbdbl_ctl->timeout_attr.show = sony_nc_kbd_backlight_timeout_show; |
1751 | kbdbl_handle->timeout_attr.store = sony_nc_kbd_backlight_timeout_store; | 1771 | kbdbl_ctl->timeout_attr.store = sony_nc_kbd_backlight_timeout_store; |
1752 | 1772 | ||
1753 | if (device_create_file(&pd->dev, &kbdbl_handle->mode_attr)) | 1773 | ret = device_create_file(&pd->dev, &kbdbl_ctl->mode_attr); |
1774 | if (ret) | ||
1754 | goto outkzalloc; | 1775 | goto outkzalloc; |
1755 | 1776 | ||
1756 | if (device_create_file(&pd->dev, &kbdbl_handle->timeout_attr)) | 1777 | ret = device_create_file(&pd->dev, &kbdbl_ctl->timeout_attr); |
1778 | if (ret) | ||
1757 | goto outmode; | 1779 | goto outmode; |
1758 | 1780 | ||
1759 | __sony_nc_kbd_backlight_mode_set(kbd_backlight); | 1781 | __sony_nc_kbd_backlight_mode_set(kbd_backlight); |
1760 | __sony_nc_kbd_backlight_timeout_set(kbd_backlight_timeout); | 1782 | __sony_nc_kbd_backlight_timeout_set(kbd_backlight_timeout); |
1761 | 1783 | ||
1762 | return; | 1784 | return 0; |
1763 | 1785 | ||
1764 | outmode: | 1786 | outmode: |
1765 | device_remove_file(&pd->dev, &kbdbl_handle->mode_attr); | 1787 | device_remove_file(&pd->dev, &kbdbl_ctl->mode_attr); |
1766 | outkzalloc: | 1788 | outkzalloc: |
1767 | kfree(kbdbl_handle); | 1789 | kfree(kbdbl_ctl); |
1768 | kbdbl_handle = NULL; | 1790 | kbdbl_ctl = NULL; |
1769 | return; | 1791 | return ret; |
1770 | } | 1792 | } |
1771 | 1793 | ||
1772 | static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd) | 1794 | static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd) |
1773 | { | 1795 | { |
1774 | if (kbdbl_handle) { | 1796 | if (kbdbl_ctl) { |
1775 | int result; | 1797 | int result; |
1776 | 1798 | ||
1777 | device_remove_file(&pd->dev, &kbdbl_handle->mode_attr); | 1799 | device_remove_file(&pd->dev, &kbdbl_ctl->mode_attr); |
1778 | device_remove_file(&pd->dev, &kbdbl_handle->timeout_attr); | 1800 | device_remove_file(&pd->dev, &kbdbl_ctl->timeout_attr); |
1779 | 1801 | ||
1780 | /* restore the default hw behaviour */ | 1802 | /* restore the default hw behaviour */ |
1781 | sony_call_snc_handle(KBDBL_HANDLER, 0x1000 | SET_MODE, &result); | 1803 | sony_call_snc_handle(kbdbl_ctl->handle, |
1782 | sony_call_snc_handle(KBDBL_HANDLER, SET_TIMEOUT, &result); | 1804 | kbdbl_ctl->base | 0x10000, &result); |
1805 | sony_call_snc_handle(kbdbl_ctl->handle, | ||
1806 | kbdbl_ctl->base + 0x200, &result); | ||
1783 | 1807 | ||
1784 | kfree(kbdbl_handle); | 1808 | kfree(kbdbl_ctl); |
1809 | kbdbl_ctl = NULL; | ||
1785 | } | 1810 | } |
1786 | return 0; | ||
1787 | } | 1811 | } |
1788 | 1812 | ||
1789 | static void sony_nc_kbd_backlight_resume(void) | 1813 | static void sony_nc_kbd_backlight_resume(void) |
1790 | { | 1814 | { |
1791 | int ignore = 0; | 1815 | int ignore = 0; |
1792 | 1816 | ||
1793 | if (!kbdbl_handle) | 1817 | if (!kbdbl_ctl) |
1794 | return; | 1818 | return; |
1795 | 1819 | ||
1796 | if (kbdbl_handle->mode == 0) | 1820 | if (kbdbl_ctl->mode == 0) |
1797 | sony_call_snc_handle(KBDBL_HANDLER, SET_MODE, &ignore); | 1821 | sony_call_snc_handle(kbdbl_ctl->handle, kbdbl_ctl->base, |
1798 | |||
1799 | if (kbdbl_handle->timeout != 0) | ||
1800 | sony_call_snc_handle(KBDBL_HANDLER, | ||
1801 | (kbdbl_handle->timeout << 0x10) | SET_TIMEOUT, | ||
1802 | &ignore); | 1822 | &ignore); |
1823 | |||
1824 | if (kbdbl_ctl->timeout != 0) | ||
1825 | sony_call_snc_handle(kbdbl_ctl->handle, | ||
1826 | (kbdbl_ctl->base + 0x200) | | ||
1827 | (kbdbl_ctl->timeout << 0x10), &ignore); | ||
1803 | } | 1828 | } |
1804 | 1829 | ||
1805 | struct battery_care_control { | 1830 | struct battery_care_control { |