1/* 2 * Driver for Semtech SX8654 I2C touchscreen controller. 3 * 4 * Copyright (c) 2015 Armadeus Systems 5 * S��bastien Szymanski <sebastien.szymanski@armadeus.com> 6 * 7 * Using code from: 8 * - sx865x.c 9 * Copyright (c) 2013 U-MoBo Srl 10 * Pierluigi Passaro <p.passaro@u-mobo.com> 11 * - sx8650.c 12 * Copyright (c) 2009 Wayne Roberts 13 * - tsc2007.c 14 * Copyright (c) 2008 Kwangwoo Lee 15 * - ads7846.c 16 * Copyright (c) 2005 David Brownell 17 * Copyright (c) 2006 Nokia Corporation 18 * - corgi_ts.c 19 * Copyright (C) 2004-2005 Richard Purdie 20 * - omap_ts.[hc], ads7846.h, ts_osk.c 21 * Copyright (C) 2002 MontaVista Software 22 * Copyright (C) 2004 Texas Instruments 23 * Copyright (C) 2005 Dirk Behme 24 * 25 * This program is free software; you can redistribute it and/or modify 26 * it under the terms of the GNU General Public License version 2 as 27 * published by the Free Software Foundation. 28 */ 29 30#include <linux/input.h> 31#include <linux/module.h> 32#include <linux/of.h> 33#include <linux/i2c.h> 34#include <linux/interrupt.h> 35#include <linux/irq.h> 36 37/* register addresses */ 38#define I2C_REG_TOUCH0 0x00 39#define I2C_REG_TOUCH1 0x01 40#define I2C_REG_CHANMASK 0x04 41#define I2C_REG_IRQMASK 0x22 42#define I2C_REG_IRQSRC 0x23 43#define I2C_REG_SOFTRESET 0x3f 44 45/* commands */ 46#define CMD_READ_REGISTER 0x40 47#define CMD_MANUAL 0xc0 48#define CMD_PENTRG 0xe0 49 50/* value for I2C_REG_SOFTRESET */ 51#define SOFTRESET_VALUE 0xde 52 53/* bits for I2C_REG_IRQSRC */ 54#define IRQ_PENTOUCH_TOUCHCONVDONE 0x08 55#define IRQ_PENRELEASE 0x04 56 57/* bits for RegTouch1 */ 58#define CONDIRQ 0x20 59#define FILT_7SA 0x03 60 61/* bits for I2C_REG_CHANMASK */ 62#define CONV_X 0x80 63#define CONV_Y 0x40 64 65/* coordinates rate: higher nibble of CTRL0 register */ 66#define RATE_MANUAL 0x00 67#define RATE_5000CPS 0xf0 68 69/* power delay: lower nibble of CTRL0 register */ 70#define POWDLY_1_1MS 0x0b 71 72#define MAX_12BIT ((1 << 12) - 1) 73 74struct sx8654 { 75 struct input_dev *input; 76 struct i2c_client *client; 77}; 78 79static irqreturn_t sx8654_irq(int irq, void *handle) 80{ 81 struct sx8654 *sx8654 = handle; 82 int irqsrc; 83 u8 data[4]; 84 unsigned int x, y; 85 int retval; 86 87 irqsrc = i2c_smbus_read_byte_data(sx8654->client, 88 CMD_READ_REGISTER | I2C_REG_IRQSRC); 89 dev_dbg(&sx8654->client->dev, "irqsrc = 0x%x", irqsrc); 90 91 if (irqsrc < 0) 92 goto out; 93 94 if (irqsrc & IRQ_PENRELEASE) { 95 dev_dbg(&sx8654->client->dev, "pen release interrupt"); 96 97 input_report_key(sx8654->input, BTN_TOUCH, 0); 98 input_sync(sx8654->input); 99 } 100 101 if (irqsrc & IRQ_PENTOUCH_TOUCHCONVDONE) { 102 dev_dbg(&sx8654->client->dev, "pen touch interrupt"); 103 104 retval = i2c_master_recv(sx8654->client, data, sizeof(data)); 105 if (retval != sizeof(data)) 106 goto out; 107 108 /* invalid data */ 109 if (unlikely(data[0] & 0x80 || data[2] & 0x80)) 110 goto out; 111 112 x = ((data[0] & 0xf) << 8) | (data[1]); 113 y = ((data[2] & 0xf) << 8) | (data[3]); 114 115 input_report_abs(sx8654->input, ABS_X, x); 116 input_report_abs(sx8654->input, ABS_Y, y); 117 input_report_key(sx8654->input, BTN_TOUCH, 1); 118 input_sync(sx8654->input); 119 120 dev_dbg(&sx8654->client->dev, "point(%4d,%4d)\n", x, y); 121 } 122 123out: 124 return IRQ_HANDLED; 125} 126 127static int sx8654_open(struct input_dev *dev) 128{ 129 struct sx8654 *sx8654 = input_get_drvdata(dev); 130 struct i2c_client *client = sx8654->client; 131 int error; 132 133 /* enable pen trigger mode */ 134 error = i2c_smbus_write_byte_data(client, I2C_REG_TOUCH0, 135 RATE_5000CPS | POWDLY_1_1MS); 136 if (error) { 137 dev_err(&client->dev, "writing to I2C_REG_TOUCH0 failed"); 138 return error; 139 } 140 141 error = i2c_smbus_write_byte(client, CMD_PENTRG); 142 if (error) { 143 dev_err(&client->dev, "writing command CMD_PENTRG failed"); 144 return error; 145 } 146 147 enable_irq(client->irq); 148 149 return 0; 150} 151 152static void sx8654_close(struct input_dev *dev) 153{ 154 struct sx8654 *sx8654 = input_get_drvdata(dev); 155 struct i2c_client *client = sx8654->client; 156 int error; 157 158 disable_irq(client->irq); 159 160 /* enable manual mode mode */ 161 error = i2c_smbus_write_byte(client, CMD_MANUAL); 162 if (error) { 163 dev_err(&client->dev, "writing command CMD_MANUAL failed"); 164 return; 165 } 166 167 error = i2c_smbus_write_byte_data(client, I2C_REG_TOUCH0, 0); 168 if (error) { 169 dev_err(&client->dev, "writing to I2C_REG_TOUCH0 failed"); 170 return; 171 } 172} 173 174static int sx8654_probe(struct i2c_client *client, 175 const struct i2c_device_id *id) 176{ 177 struct sx8654 *sx8654; 178 struct input_dev *input; 179 int error; 180 181 if (!i2c_check_functionality(client->adapter, 182 I2C_FUNC_SMBUS_READ_WORD_DATA)) 183 return -ENXIO; 184 185 sx8654 = devm_kzalloc(&client->dev, sizeof(*sx8654), GFP_KERNEL); 186 if (!sx8654) 187 return -ENOMEM; 188 189 input = devm_input_allocate_device(&client->dev); 190 if (!input) 191 return -ENOMEM; 192 193 input->name = "SX8654 I2C Touchscreen"; 194 input->id.bustype = BUS_I2C; 195 input->dev.parent = &client->dev; 196 input->open = sx8654_open; 197 input->close = sx8654_close; 198 199 __set_bit(INPUT_PROP_DIRECT, input->propbit); 200 input_set_capability(input, EV_KEY, BTN_TOUCH); 201 input_set_abs_params(input, ABS_X, 0, MAX_12BIT, 0, 0); 202 input_set_abs_params(input, ABS_Y, 0, MAX_12BIT, 0, 0); 203 204 sx8654->client = client; 205 sx8654->input = input; 206 207 input_set_drvdata(sx8654->input, sx8654); 208 209 error = i2c_smbus_write_byte_data(client, I2C_REG_SOFTRESET, 210 SOFTRESET_VALUE); 211 if (error) { 212 dev_err(&client->dev, "writing softreset value failed"); 213 return error; 214 } 215 216 error = i2c_smbus_write_byte_data(client, I2C_REG_CHANMASK, 217 CONV_X | CONV_Y); 218 if (error) { 219 dev_err(&client->dev, "writing to I2C_REG_CHANMASK failed"); 220 return error; 221 } 222 223 error = i2c_smbus_write_byte_data(client, I2C_REG_IRQMASK, 224 IRQ_PENTOUCH_TOUCHCONVDONE | 225 IRQ_PENRELEASE); 226 if (error) { 227 dev_err(&client->dev, "writing to I2C_REG_IRQMASK failed"); 228 return error; 229 } 230 231 error = i2c_smbus_write_byte_data(client, I2C_REG_TOUCH1, 232 CONDIRQ | FILT_7SA); 233 if (error) { 234 dev_err(&client->dev, "writing to I2C_REG_TOUCH1 failed"); 235 return error; 236 } 237 238 error = devm_request_threaded_irq(&client->dev, client->irq, 239 NULL, sx8654_irq, 240 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 241 client->name, sx8654); 242 if (error) { 243 dev_err(&client->dev, 244 "Failed to enable IRQ %d, error: %d\n", 245 client->irq, error); 246 return error; 247 } 248 249 /* Disable the IRQ, we'll enable it in sx8654_open() */ 250 disable_irq(client->irq); 251 252 error = input_register_device(sx8654->input); 253 if (error) 254 return error; 255 256 i2c_set_clientdata(client, sx8654); 257 return 0; 258} 259 260#ifdef CONFIG_OF 261static const struct of_device_id sx8654_of_match[] = { 262 { .compatible = "semtech,sx8654", }, 263 { }, 264}; 265MODULE_DEVICE_TABLE(of, sx8654_of_match); 266#endif 267 268static const struct i2c_device_id sx8654_id_table[] = { 269 { "semtech_sx8654", 0 }, 270 { }, 271}; 272MODULE_DEVICE_TABLE(i2c, sx8654_id_table); 273 274static struct i2c_driver sx8654_driver = { 275 .driver = { 276 .name = "sx8654", 277 .of_match_table = of_match_ptr(sx8654_of_match), 278 }, 279 .id_table = sx8654_id_table, 280 .probe = sx8654_probe, 281}; 282module_i2c_driver(sx8654_driver); 283 284MODULE_AUTHOR("S��bastien Szymanski <sebastien.szymanski@armadeus.com>"); 285MODULE_DESCRIPTION("Semtech SX8654 I2C Touchscreen Driver"); 286MODULE_LICENSE("GPL"); 287