aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorMarco Chiappero <marco@absence.it>2012-05-19 09:35:56 -0400
committerMatthew Garrett <mjg@redhat.com>2012-05-31 14:34:42 -0400
commitaa33924f35842cc7544865fd13713d1bb88aee65 (patch)
treeceb4da83e5b20b4e5d6d4ee2aa5297af9edbeeb4 /drivers/platform
parent88bf170646c3673877f4449127c2940c0bc307ca (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')
-rw-r--r--drivers/platform/x86/sony-laptop.c149
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
143static void sony_nc_kbd_backlight_resume(void); 143static void sony_nc_kbd_backlight_resume(void);
144static void sony_nc_kbd_backlight_setup(struct platform_device *pd); 144static int sony_nc_kbd_backlight_setup(struct platform_device *pd,
145static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd); 145 unsigned int handle);
146static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd);
146 147
147static int sony_nc_battery_care_setup(struct platform_device *pd, 148static 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
1627struct kbd_backlight { 1628struct 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
1634static struct kbd_backlight *kbdbl_handle; 1637static struct kbd_backlight *kbdbl_ctl;
1635 1638
1636static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value) 1639static 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
1728static void sony_nc_kbd_backlight_setup(struct platform_device *pd) 1731static 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
1764outmode: 1786outmode:
1765 device_remove_file(&pd->dev, &kbdbl_handle->mode_attr); 1787 device_remove_file(&pd->dev, &kbdbl_ctl->mode_attr);
1766outkzalloc: 1788outkzalloc:
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
1772static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd) 1794static 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
1789static void sony_nc_kbd_backlight_resume(void) 1813static 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
1805struct battery_care_control { 1830struct battery_care_control {