15a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita/* 25a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita * Wacom Penabled Driver for I2C 35a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita * 48855f30cd2b68012571932c7b01290c20be4508cTatsunosuke Tobita * Copyright (c) 2011 - 2013 Tatsunosuke Tobita, Wacom. 55a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita * <tobita.tatsunosuke@wacom.co.jp> 65a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita * 75a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita * This program is free software; you can redistribute it 85a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita * and/or modify it under the terms of the GNU General 95a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita * Public License as published by the Free Software 105a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita * Foundation; either version of 2 of the License, 115a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita * or (at your option) any later version. 125a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita */ 135a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 145a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita#include <linux/module.h> 155a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita#include <linux/input.h> 165a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita#include <linux/i2c.h> 175a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita#include <linux/slab.h> 185a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita#include <linux/irq.h> 195a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita#include <linux/interrupt.h> 205a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita#include <linux/gpio.h> 215a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita#include <asm/unaligned.h> 225a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 235a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita#define WACOM_CMD_QUERY0 0x04 245a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita#define WACOM_CMD_QUERY1 0x00 255a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita#define WACOM_CMD_QUERY2 0x33 265a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita#define WACOM_CMD_QUERY3 0x02 275a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita#define WACOM_CMD_THROW0 0x05 285a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita#define WACOM_CMD_THROW1 0x00 295a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita#define WACOM_QUERY_SIZE 19 305a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 315a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobitastruct wacom_features { 325a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita int x_max; 335a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita int y_max; 345a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita int pressure_max; 355a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita char fw_version; 365a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita}; 375a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 385a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobitastruct wacom_i2c { 395a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita struct i2c_client *client; 405a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita struct input_dev *input; 415a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita u8 data[WACOM_QUERY_SIZE]; 428855f30cd2b68012571932c7b01290c20be4508cTatsunosuke Tobita bool prox; 438855f30cd2b68012571932c7b01290c20be4508cTatsunosuke Tobita int tool; 445a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita}; 455a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 465a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobitastatic int wacom_query_device(struct i2c_client *client, 475a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita struct wacom_features *features) 485a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita{ 495a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita int ret; 505a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita u8 cmd1[] = { WACOM_CMD_QUERY0, WACOM_CMD_QUERY1, 515a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita WACOM_CMD_QUERY2, WACOM_CMD_QUERY3 }; 525a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita u8 cmd2[] = { WACOM_CMD_THROW0, WACOM_CMD_THROW1 }; 535a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita u8 data[WACOM_QUERY_SIZE]; 545a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita struct i2c_msg msgs[] = { 555a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita { 565a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita .addr = client->addr, 575a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita .flags = 0, 585a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita .len = sizeof(cmd1), 595a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita .buf = cmd1, 605a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita }, 615a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita { 625a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita .addr = client->addr, 635a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita .flags = 0, 645a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita .len = sizeof(cmd2), 655a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita .buf = cmd2, 665a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita }, 675a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita { 685a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita .addr = client->addr, 695a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita .flags = I2C_M_RD, 705a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita .len = sizeof(data), 715a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita .buf = data, 725a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita }, 735a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita }; 745a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 755a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); 765a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita if (ret < 0) 775a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita return ret; 785a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita if (ret != ARRAY_SIZE(msgs)) 795a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita return -EIO; 805a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 815a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita features->x_max = get_unaligned_le16(&data[3]); 825a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita features->y_max = get_unaligned_le16(&data[5]); 835a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita features->pressure_max = get_unaligned_le16(&data[11]); 845a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita features->fw_version = get_unaligned_le16(&data[13]); 855a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 865a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita dev_dbg(&client->dev, 875a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita "x_max:%d, y_max:%d, pressure:%d, fw:%d\n", 885a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita features->x_max, features->y_max, 895a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita features->pressure_max, features->fw_version); 905a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 915a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita return 0; 925a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita} 935a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 945a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobitastatic irqreturn_t wacom_i2c_irq(int irq, void *dev_id) 955a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita{ 965a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita struct wacom_i2c *wac_i2c = dev_id; 975a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita struct input_dev *input = wac_i2c->input; 985a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita u8 *data = wac_i2c->data; 995a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita unsigned int x, y, pressure; 1005a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita unsigned char tsw, f1, f2, ers; 1015a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita int error; 1025a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 103d568778298f58330bcc8cc23845676d1143c8d33Dmitry Torokhov error = i2c_master_recv(wac_i2c->client, 104d568778298f58330bcc8cc23845676d1143c8d33Dmitry Torokhov wac_i2c->data, sizeof(wac_i2c->data)); 105d568778298f58330bcc8cc23845676d1143c8d33Dmitry Torokhov if (error < 0) 1065a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita goto out; 1075a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 1085a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita tsw = data[3] & 0x01; 1095a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita ers = data[3] & 0x04; 1105a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita f1 = data[3] & 0x02; 1115a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita f2 = data[3] & 0x10; 1125a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita x = le16_to_cpup((__le16 *)&data[4]); 1135a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita y = le16_to_cpup((__le16 *)&data[6]); 1145a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita pressure = le16_to_cpup((__le16 *)&data[8]); 1155a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 1168855f30cd2b68012571932c7b01290c20be4508cTatsunosuke Tobita if (!wac_i2c->prox) 1178855f30cd2b68012571932c7b01290c20be4508cTatsunosuke Tobita wac_i2c->tool = (data[3] & 0x0c) ? 1188855f30cd2b68012571932c7b01290c20be4508cTatsunosuke Tobita BTN_TOOL_RUBBER : BTN_TOOL_PEN; 1198855f30cd2b68012571932c7b01290c20be4508cTatsunosuke Tobita 1208855f30cd2b68012571932c7b01290c20be4508cTatsunosuke Tobita wac_i2c->prox = data[3] & 0x20; 1218855f30cd2b68012571932c7b01290c20be4508cTatsunosuke Tobita 1225a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita input_report_key(input, BTN_TOUCH, tsw || ers); 1238855f30cd2b68012571932c7b01290c20be4508cTatsunosuke Tobita input_report_key(input, wac_i2c->tool, wac_i2c->prox); 1245a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita input_report_key(input, BTN_STYLUS, f1); 1255a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita input_report_key(input, BTN_STYLUS2, f2); 1265a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita input_report_abs(input, ABS_X, x); 1275a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita input_report_abs(input, ABS_Y, y); 1285a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita input_report_abs(input, ABS_PRESSURE, pressure); 1295a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita input_sync(input); 1305a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 1315a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobitaout: 1325a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita return IRQ_HANDLED; 1335a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita} 1345a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 1355a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobitastatic int wacom_i2c_open(struct input_dev *dev) 1365a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita{ 1375a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita struct wacom_i2c *wac_i2c = input_get_drvdata(dev); 1385a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita struct i2c_client *client = wac_i2c->client; 1395a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 1405a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita enable_irq(client->irq); 1415a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 1425a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita return 0; 1435a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita} 1445a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 1455a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobitastatic void wacom_i2c_close(struct input_dev *dev) 1465a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita{ 1475a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita struct wacom_i2c *wac_i2c = input_get_drvdata(dev); 1485a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita struct i2c_client *client = wac_i2c->client; 1495a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 1505a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita disable_irq(client->irq); 1515a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita} 1525a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 1535298cc4cc753bbe4c530b41341834f6ef3344d0dBill Pembertonstatic int wacom_i2c_probe(struct i2c_client *client, 1545a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita const struct i2c_device_id *id) 1555a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita{ 1565a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita struct wacom_i2c *wac_i2c; 1575a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita struct input_dev *input; 1588830cb88dd6d60c3bb4cb46d8a855628e4875b18Dmitry Torokhov struct wacom_features features = { 0 }; 1595a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita int error; 1605a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 1615a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 1625a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita dev_err(&client->dev, "i2c_check_functionality error\n"); 1635a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita return -EIO; 1645a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita } 1655a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 1665a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita error = wacom_query_device(client, &features); 1675a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita if (error) 1685a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita return error; 1695a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 1705a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita wac_i2c = kzalloc(sizeof(*wac_i2c), GFP_KERNEL); 1715a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita input = input_allocate_device(); 1725a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita if (!wac_i2c || !input) { 1735a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita error = -ENOMEM; 1745a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita goto err_free_mem; 1755a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita } 1765a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 1775a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita wac_i2c->client = client; 1785a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita wac_i2c->input = input; 1795a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 1805a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita input->name = "Wacom I2C Digitizer"; 1815a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita input->id.bustype = BUS_I2C; 1825a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita input->id.vendor = 0x56a; 1835a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita input->id.version = features.fw_version; 1845a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita input->dev.parent = &client->dev; 1855a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita input->open = wacom_i2c_open; 1865a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita input->close = wacom_i2c_close; 1875a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 1885a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita input->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 1895a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 1905a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita __set_bit(BTN_TOOL_PEN, input->keybit); 1915a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita __set_bit(BTN_TOOL_RUBBER, input->keybit); 1925a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita __set_bit(BTN_STYLUS, input->keybit); 1935a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita __set_bit(BTN_STYLUS2, input->keybit); 1945a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita __set_bit(BTN_TOUCH, input->keybit); 1955a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 1965a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita input_set_abs_params(input, ABS_X, 0, features.x_max, 0, 0); 1975a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita input_set_abs_params(input, ABS_Y, 0, features.y_max, 0, 0); 1985a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita input_set_abs_params(input, ABS_PRESSURE, 1995a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 0, features.pressure_max, 0, 0); 2005a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 2015a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita input_set_drvdata(input, wac_i2c); 2025a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 2035a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita error = request_threaded_irq(client->irq, NULL, wacom_i2c_irq, 204d568778298f58330bcc8cc23845676d1143c8d33Dmitry Torokhov IRQF_TRIGGER_LOW | IRQF_ONESHOT, 2055a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita "wacom_i2c", wac_i2c); 2065a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita if (error) { 2075a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita dev_err(&client->dev, 2085a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita "Failed to enable IRQ, error: %d\n", error); 2095a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita goto err_free_mem; 2105a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita } 2115a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 2125a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita /* Disable the IRQ, we'll enable it in wac_i2c_open() */ 2135a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita disable_irq(client->irq); 2145a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 2155a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita error = input_register_device(wac_i2c->input); 2165a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita if (error) { 2175a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita dev_err(&client->dev, 2185a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita "Failed to register input device, error: %d\n", error); 2195a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita goto err_free_irq; 2205a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita } 2215a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 2225a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita i2c_set_clientdata(client, wac_i2c); 2235a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita return 0; 2245a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 2255a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobitaerr_free_irq: 2265a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita free_irq(client->irq, wac_i2c); 2275a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobitaerr_free_mem: 2285a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita input_free_device(input); 2295a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita kfree(wac_i2c); 2305a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 2315a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita return error; 2325a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita} 2335a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 234e2619cf78e19476bfd7ceaefa9eff0847529346eBill Pembertonstatic int wacom_i2c_remove(struct i2c_client *client) 2355a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita{ 2365a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita struct wacom_i2c *wac_i2c = i2c_get_clientdata(client); 2375a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 2385a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita free_irq(client->irq, wac_i2c); 2395a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita input_unregister_device(wac_i2c->input); 2405a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita kfree(wac_i2c); 2415a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 2425a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita return 0; 2435a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita} 2445a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 2455a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita#ifdef CONFIG_PM_SLEEP 2465a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobitastatic int wacom_i2c_suspend(struct device *dev) 2475a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita{ 2485a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita struct i2c_client *client = to_i2c_client(dev); 2495a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 2505a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita disable_irq(client->irq); 2515a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 2525a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita return 0; 2535a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita} 2545a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 2555a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobitastatic int wacom_i2c_resume(struct device *dev) 2565a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita{ 2575a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita struct i2c_client *client = to_i2c_client(dev); 2585a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 2595a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita enable_irq(client->irq); 2605a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 2615a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita return 0; 2625a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita} 2635a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita#endif 2645a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 2655a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobitastatic SIMPLE_DEV_PM_OPS(wacom_i2c_pm, wacom_i2c_suspend, wacom_i2c_resume); 2665a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 2675a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobitastatic const struct i2c_device_id wacom_i2c_id[] = { 2685a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita { "WAC_I2C_EMR", 0 }, 2695a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita { }, 2705a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita}; 2715a966261c0dfb836f54444ff3893638802183cacTatsunosuke TobitaMODULE_DEVICE_TABLE(i2c, wacom_i2c_id); 2725a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 2735a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobitastatic struct i2c_driver wacom_i2c_driver = { 2745a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita .driver = { 2755a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita .name = "wacom_i2c", 2765a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita .owner = THIS_MODULE, 2775a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita .pm = &wacom_i2c_pm, 2785a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita }, 2795a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 2805a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita .probe = wacom_i2c_probe, 2811cb0aa88179b7a71c240529e9d781d7bbb43d2e8Bill Pemberton .remove = wacom_i2c_remove, 2825a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita .id_table = wacom_i2c_id, 2835a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita}; 2845a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobitamodule_i2c_driver(wacom_i2c_driver); 2855a966261c0dfb836f54444ff3893638802183cacTatsunosuke Tobita 2865a966261c0dfb836f54444ff3893638802183cacTatsunosuke TobitaMODULE_AUTHOR("Tatsunosuke Tobita <tobita.tatsunosuke@wacom.co.jp>"); 2875a966261c0dfb836f54444ff3893638802183cacTatsunosuke TobitaMODULE_DESCRIPTION("WACOM EMR I2C Driver"); 2885a966261c0dfb836f54444ff3893638802183cacTatsunosuke TobitaMODULE_LICENSE("GPL"); 289