diff options
| -rw-r--r-- | drivers/hid/i2c-hid/i2c-hid.c | 87 |
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 | ||
| 144 | static int __i2c_hid_command(struct i2c_client *client, | 147 | static 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 | ||
| 817 | static 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 | |||
| 866 | static const struct acpi_device_id i2c_hid_acpi_match[] = { | ||
| 867 | {"ACPI0C50", 0 }, | ||
| 868 | {"PNP0C50", 0 }, | ||
| 869 | { }, | ||
| 870 | }; | ||
| 871 | MODULE_DEVICE_TABLE(acpi, i2c_hid_acpi_match); | ||
| 872 | #else | ||
| 873 | static 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 | |||
| 813 | static int __devinit i2c_hid_probe(struct i2c_client *client, | 880 | static 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, |
