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 74 struct sx8654 { 75 struct input_dev *input; 76 struct i2c_client *client; 77 }; 78 79 static 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 123 out: 124 return IRQ_HANDLED; 125 } 126 127 static 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 152 static 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 174 static 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 return 0; 257 } 258 259 #ifdef CONFIG_OF 260 static const struct of_device_id sx8654_of_match[] = { 261 { .compatible = "semtech,sx8654", }, 262 { }, 263 }; 264 MODULE_DEVICE_TABLE(of, sx8654_of_match); 265 #endif 266 267 static const struct i2c_device_id sx8654_id_table[] = { 268 { "semtech_sx8654", 0 }, 269 { }, 270 }; 271 MODULE_DEVICE_TABLE(i2c, sx8654_id_table); 272 273 static struct i2c_driver sx8654_driver = { 274 .driver = { 275 .name = "sx8654", 276 .of_match_table = of_match_ptr(sx8654_of_match), 277 }, 278 .id_table = sx8654_id_table, 279 .probe = sx8654_probe, 280 }; 281 module_i2c_driver(sx8654_driver); 282 283 MODULE_AUTHOR("Sébastien Szymanski <sebastien.szymanski@armadeus.com>"); 284 MODULE_DESCRIPTION("Semtech SX8654 I2C Touchscreen Driver"); 285 MODULE_LICENSE("GPL"); 286