diff options
Diffstat (limited to 'drivers/hid/i2c-hid/i2c-hid.c')
-rw-r--r-- | drivers/hid/i2c-hid/i2c-hid.c | 77 |
1 files changed, 48 insertions, 29 deletions
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index 879b0ed701a..c1336193b04 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -35,6 +35,7 @@ #include <linux/hid.h> #include <linux/mutex.h> #include <linux/acpi.h> +#include <linux/of.h> #include <linux/i2c/i2c-hid.h> @@ -756,29 +757,6 @@ static int i2c_hid_power(struct hid_device *hid, int lvl) return ret; } -static int i2c_hid_hidinput_input_event(struct input_dev *dev, - unsigned int type, unsigned int code, int value) -{ - struct hid_device *hid = input_get_drvdata(dev); - struct hid_field *field; - int offset; - - if (type == EV_FF) - return input_ff_event(dev, type, code, value); - - if (type != EV_LED) - return -1; - - offset = hidinput_find_field(hid, type, code, &field); - - if (offset == -1) { - hid_warn(dev, "event field not found\n"); - return -1; - } - - return hid_set_field(field, offset, value); -} - static struct hid_ll_driver i2c_hid_ll_driver = { .parse = i2c_hid_parse, .start = i2c_hid_start, @@ -787,7 +765,6 @@ static struct hid_ll_driver i2c_hid_ll_driver = { .close = i2c_hid_close, .power = i2c_hid_power, .request = i2c_hid_request, - .hidinput_input_event = i2c_hid_hidinput_input_event, }; static int i2c_hid_init_irq(struct i2c_client *client) @@ -824,8 +801,8 @@ static int i2c_hid_fetch_hid_descriptor(struct i2c_hid *ihid) * bytes 2-3 -> bcdVersion (has to be 1.00) */ ret = i2c_hid_command(client, &hid_descr_cmd, ihid->hdesc_buffer, 4); - i2c_hid_dbg(ihid, "%s, ihid->hdesc_buffer: %*ph\n", - __func__, 4, ihid->hdesc_buffer); + i2c_hid_dbg(ihid, "%s, ihid->hdesc_buffer: %4ph\n", __func__, + ihid->hdesc_buffer); if (ret) { dev_err(&client->dev, @@ -897,8 +874,9 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client, params[1].integer.value = 1; params[2].type = ACPI_TYPE_INTEGER; params[2].integer.value = 1; /* HID function */ - params[3].type = ACPI_TYPE_INTEGER; - params[3].integer.value = 0; + params[3].type = ACPI_TYPE_PACKAGE; + params[3].package.count = 0; + params[3].package.elements = NULL; if (ACPI_FAILURE(acpi_evaluate_object(handle, "_DSM", &input, &buf))) { dev_err(&client->dev, "device _DSM execution failed\n"); @@ -933,6 +911,42 @@ static inline int i2c_hid_acpi_pdata(struct i2c_client *client, } #endif +#ifdef CONFIG_OF +static int i2c_hid_of_probe(struct i2c_client *client, + struct i2c_hid_platform_data *pdata) +{ + struct device *dev = &client->dev; + u32 val; + int ret; + + ret = of_property_read_u32(dev->of_node, "hid-descr-addr", &val); + if (ret) { + dev_err(&client->dev, "HID register address not provided\n"); + return -ENODEV; + } + if (val >> 16) { + dev_err(&client->dev, "Bad HID register address: 0x%08x\n", + val); + return -EINVAL; + } + pdata->hid_descriptor_address = val; + + return 0; +} + +static const struct of_device_id i2c_hid_of_match[] = { + { .compatible = "hid-over-i2c" }, + {}, +}; +MODULE_DEVICE_TABLE(of, i2c_hid_of_match); +#else +static inline int i2c_hid_of_probe(struct i2c_client *client, + struct i2c_hid_platform_data *pdata) +{ + return -ENODEV; +} +#endif + static int i2c_hid_probe(struct i2c_client *client, const struct i2c_device_id *dev_id) { @@ -954,7 +968,11 @@ static int i2c_hid_probe(struct i2c_client *client, if (!ihid) return -ENOMEM; - if (!platform_data) { + if (client->dev.of_node) { + ret = i2c_hid_of_probe(client, &ihid->pdata); + if (ret) + goto err; + } else if (!platform_data) { ret = i2c_hid_acpi_pdata(client, &ihid->pdata); if (ret) { dev_err(&client->dev, @@ -1095,6 +1113,7 @@ static struct i2c_driver i2c_hid_driver = { .owner = THIS_MODULE, .pm = &i2c_hid_pm, .acpi_match_table = ACPI_PTR(i2c_hid_acpi_match), + .of_match_table = of_match_ptr(i2c_hid_of_match), }, .probe = i2c_hid_probe, |