aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/i2c-hid
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2013-01-09 09:43:08 -0500
committerJiri Kosina <jkosina@suse.cz>2013-01-18 05:38:29 -0500
commit92241e67c0acf21421cda214bdf877c8c030e556 (patch)
tree145e82a7cc13dfe21b01a587133a87f773aaac29 /drivers/hid/i2c-hid
parentfd62c5450324af7f6cc12897b09b77285cd48a92 (diff)
HID: i2c-hid: add ACPI support
The HID over I2C protocol specification states that when the device is enumerated from ACPI the HID descriptor address can be obtained by executing "_DSM" for the device with function 1. Enable this. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/i2c-hid')
-rw-r--r--drivers/hid/i2c-hid/i2c-hid.c87
1 files changed, 81 insertions, 6 deletions
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index 9ef222442ca0..9e46e4295bd9 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -34,6 +34,7 @@
34#include <linux/kernel.h> 34#include <linux/kernel.h>
35#include <linux/hid.h> 35#include <linux/hid.h>
36#include <linux/mutex.h> 36#include <linux/mutex.h>
37#include <linux/acpi.h>
37 38
38#include <linux/i2c/i2c-hid.h> 39#include <linux/i2c/i2c-hid.h>
39 40
@@ -139,6 +140,8 @@ struct i2c_hid {
139 unsigned long flags; /* device flags */ 140 unsigned long flags; /* device flags */
140 141
141 wait_queue_head_t wait; /* For waiting the interrupt */ 142 wait_queue_head_t wait; /* For waiting the interrupt */
143
144 struct i2c_hid_platform_data pdata;
142}; 145};
143 146
144static int __i2c_hid_command(struct i2c_client *client, 147static int __i2c_hid_command(struct i2c_client *client,
@@ -810,6 +813,70 @@ static int __devinit i2c_hid_fetch_hid_descriptor(struct i2c_hid *ihid)
810 return 0; 813 return 0;
811} 814}
812 815
816#ifdef CONFIG_ACPI
817static int i2c_hid_acpi_pdata(struct i2c_client *client,
818 struct i2c_hid_platform_data *pdata)
819{
820 static u8 i2c_hid_guid[] = {
821 0xF7, 0xF6, 0xDF, 0x3C, 0x67, 0x42, 0x55, 0x45,
822 0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE,
823 };
824 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
825 union acpi_object params[4], *obj;
826 struct acpi_object_list input;
827 struct acpi_device *adev;
828 acpi_handle handle;
829
830 handle = ACPI_HANDLE(&client->dev);
831 if (!handle || acpi_bus_get_device(handle, &adev))
832 return -ENODEV;
833
834 input.count = ARRAY_SIZE(params);
835 input.pointer = params;
836
837 params[0].type = ACPI_TYPE_BUFFER;
838 params[0].buffer.length = sizeof(i2c_hid_guid);
839 params[0].buffer.pointer = i2c_hid_guid;
840 params[1].type = ACPI_TYPE_INTEGER;
841 params[1].integer.value = 1;
842 params[2].type = ACPI_TYPE_INTEGER;
843 params[2].integer.value = 1; /* HID function */
844 params[3].type = ACPI_TYPE_INTEGER;
845 params[3].integer.value = 0;
846
847 if (ACPI_FAILURE(acpi_evaluate_object(handle, "_DSM", &input, &buf))) {
848 dev_err(&client->dev, "device _DSM execution failed\n");
849 return -ENODEV;
850 }
851
852 obj = (union acpi_object *)buf.pointer;
853 if (obj->type != ACPI_TYPE_INTEGER) {
854 dev_err(&client->dev, "device _DSM returned invalid type: %d\n",
855 obj->type);
856 kfree(buf.pointer);
857 return -EINVAL;
858 }
859
860 pdata->hid_descriptor_address = obj->integer.value;
861
862 kfree(buf.pointer);
863 return 0;
864}
865
866static const struct acpi_device_id i2c_hid_acpi_match[] = {
867 {"ACPI0C50", 0 },
868 {"PNP0C50", 0 },
869 { },
870};
871MODULE_DEVICE_TABLE(acpi, i2c_hid_acpi_match);
872#else
873static inline int i2c_hid_acpi_pdata(struct i2c_client *client,
874 struct i2c_hid_platform_data *pdata)
875{
876 return -ENODEV;
877}
878#endif
879
813static int __devinit i2c_hid_probe(struct i2c_client *client, 880static int __devinit i2c_hid_probe(struct i2c_client *client,
814 const struct i2c_device_id *dev_id) 881 const struct i2c_device_id *dev_id)
815{ 882{
@@ -821,11 +888,6 @@ static int __devinit i2c_hid_probe(struct i2c_client *client,
821 888
822 dbg_hid("HID probe called for i2c 0x%02x\n", client->addr); 889 dbg_hid("HID probe called for i2c 0x%02x\n", client->addr);
823 890
824 if (!platform_data) {
825 dev_err(&client->dev, "HID register address not provided\n");
826 return -EINVAL;
827 }
828
829 if (!client->irq) { 891 if (!client->irq) {
830 dev_err(&client->dev, 892 dev_err(&client->dev,
831 "HID over i2c has not been provided an Int IRQ\n"); 893 "HID over i2c has not been provided an Int IRQ\n");
@@ -836,11 +898,22 @@ static int __devinit i2c_hid_probe(struct i2c_client *client,
836 if (!ihid) 898 if (!ihid)
837 return -ENOMEM; 899 return -ENOMEM;
838 900
901 if (!platform_data) {
902 ret = i2c_hid_acpi_pdata(client, &ihid->pdata);
903 if (ret) {
904 dev_err(&client->dev,
905 "HID register address not provided\n");
906 goto err;
907 }
908 } else {
909 ihid->pdata = *platform_data;
910 }
911
839 i2c_set_clientdata(client, ihid); 912 i2c_set_clientdata(client, ihid);
840 913
841 ihid->client = client; 914 ihid->client = client;
842 915
843 hidRegister = platform_data->hid_descriptor_address; 916 hidRegister = ihid->pdata.hid_descriptor_address;
844 ihid->wHIDDescRegister = cpu_to_le16(hidRegister); 917 ihid->wHIDDescRegister = cpu_to_le16(hidRegister);
845 918
846 init_waitqueue_head(&ihid->wait); 919 init_waitqueue_head(&ihid->wait);
@@ -873,6 +946,7 @@ static int __devinit i2c_hid_probe(struct i2c_client *client,
873 hid->hid_get_raw_report = i2c_hid_get_raw_report; 946 hid->hid_get_raw_report = i2c_hid_get_raw_report;
874 hid->hid_output_raw_report = i2c_hid_output_raw_report; 947 hid->hid_output_raw_report = i2c_hid_output_raw_report;
875 hid->dev.parent = &client->dev; 948 hid->dev.parent = &client->dev;
949 ACPI_HANDLE_SET(&hid->dev, ACPI_HANDLE(&client->dev));
876 hid->bus = BUS_I2C; 950 hid->bus = BUS_I2C;
877 hid->version = le16_to_cpu(ihid->hdesc.bcdVersion); 951 hid->version = le16_to_cpu(ihid->hdesc.bcdVersion);
878 hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID); 952 hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID);
@@ -964,6 +1038,7 @@ static struct i2c_driver i2c_hid_driver = {
964 .name = "i2c_hid", 1038 .name = "i2c_hid",
965 .owner = THIS_MODULE, 1039 .owner = THIS_MODULE,
966 .pm = &i2c_hid_pm, 1040 .pm = &i2c_hid_pm,
1041 .acpi_match_table = ACPI_PTR(i2c_hid_acpi_match),
967 }, 1042 },
968 1043
969 .probe = i2c_hid_probe, 1044 .probe = i2c_hid_probe,