1/* 2 * Driver for cypress touch screen controller 3 * 4 * Copyright (c) 2009 Aava Mobile 5 * 6 * Some cleanups by Alan Cox <alan@linux.intel.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 */ 21 22#include <linux/module.h> 23#include <linux/kernel.h> 24#include <linux/input.h> 25#include <linux/slab.h> 26#include <linux/interrupt.h> 27#include <linux/io.h> 28#include <linux/i2c.h> 29#include <linux/gpio.h> 30#include <linux/input/cy8ctmg110_pdata.h> 31 32#define CY8CTMG110_DRIVER_NAME "cy8ctmg110" 33 34/* Touch coordinates */ 35#define CY8CTMG110_X_MIN 0 36#define CY8CTMG110_Y_MIN 0 37#define CY8CTMG110_X_MAX 759 38#define CY8CTMG110_Y_MAX 465 39 40 41/* cy8ctmg110 register definitions */ 42#define CY8CTMG110_TOUCH_WAKEUP_TIME 0 43#define CY8CTMG110_TOUCH_SLEEP_TIME 2 44#define CY8CTMG110_TOUCH_X1 3 45#define CY8CTMG110_TOUCH_Y1 5 46#define CY8CTMG110_TOUCH_X2 7 47#define CY8CTMG110_TOUCH_Y2 9 48#define CY8CTMG110_FINGERS 11 49#define CY8CTMG110_GESTURE 12 50#define CY8CTMG110_REG_MAX 13 51 52 53/* 54 * The touch driver structure. 55 */ 56struct cy8ctmg110 { 57 struct input_dev *input; 58 char phys[32]; 59 struct i2c_client *client; 60 int reset_pin; 61 int irq_pin; 62}; 63 64/* 65 * cy8ctmg110_power is the routine that is called when touch hardware 66 * will powered off or on. 67 */ 68static void cy8ctmg110_power(struct cy8ctmg110 *ts, bool poweron) 69{ 70 if (ts->reset_pin) 71 gpio_direction_output(ts->reset_pin, 1 - poweron); 72} 73 74static int cy8ctmg110_write_regs(struct cy8ctmg110 *tsc, unsigned char reg, 75 unsigned char len, unsigned char *value) 76{ 77 struct i2c_client *client = tsc->client; 78 int ret; 79 unsigned char i2c_data[6]; 80 81 BUG_ON(len > 5); 82 83 i2c_data[0] = reg; 84 memcpy(i2c_data + 1, value, len); 85 86 ret = i2c_master_send(client, i2c_data, len + 1); 87 if (ret != len + 1) { 88 dev_err(&client->dev, "i2c write data cmd failed\n"); 89 return ret < 0 ? ret : -EIO; 90 } 91 92 return 0; 93} 94 95static int cy8ctmg110_read_regs(struct cy8ctmg110 *tsc, 96 unsigned char *data, unsigned char len, unsigned char cmd) 97{ 98 struct i2c_client *client = tsc->client; 99 int ret; 100 struct i2c_msg msg[2] = { 101 /* first write slave position to i2c devices */ 102 { 103 .addr = client->addr, 104 .len = 1, 105 .buf = &cmd 106 }, 107 /* Second read data from position */ 108 { 109 .addr = client->addr, 110 .flags = I2C_M_RD, 111 .len = len, 112 .buf = data 113 } 114 }; 115 116 ret = i2c_transfer(client->adapter, msg, 2); 117 if (ret < 0) 118 return ret; 119 120 return 0; 121} 122 123static int cy8ctmg110_touch_pos(struct cy8ctmg110 *tsc) 124{ 125 struct input_dev *input = tsc->input; 126 unsigned char reg_p[CY8CTMG110_REG_MAX]; 127 int x, y; 128 129 memset(reg_p, 0, CY8CTMG110_REG_MAX); 130 131 /* Reading coordinates */ 132 if (cy8ctmg110_read_regs(tsc, reg_p, 9, CY8CTMG110_TOUCH_X1) != 0) 133 return -EIO; 134 135 y = reg_p[2] << 8 | reg_p[3]; 136 x = reg_p[0] << 8 | reg_p[1]; 137 138 /* Number of touch */ 139 if (reg_p[8] == 0) { 140 input_report_key(input, BTN_TOUCH, 0); 141 } else { 142 input_report_key(input, BTN_TOUCH, 1); 143 input_report_abs(input, ABS_X, x); 144 input_report_abs(input, ABS_Y, y); 145 } 146 147 input_sync(input); 148 149 return 0; 150} 151 152static int cy8ctmg110_set_sleepmode(struct cy8ctmg110 *ts, bool sleep) 153{ 154 unsigned char reg_p[3]; 155 156 if (sleep) { 157 reg_p[0] = 0x00; 158 reg_p[1] = 0xff; 159 reg_p[2] = 5; 160 } else { 161 reg_p[0] = 0x10; 162 reg_p[1] = 0xff; 163 reg_p[2] = 0; 164 } 165 166 return cy8ctmg110_write_regs(ts, CY8CTMG110_TOUCH_WAKEUP_TIME, 3, reg_p); 167} 168 169static irqreturn_t cy8ctmg110_irq_thread(int irq, void *dev_id) 170{ 171 struct cy8ctmg110 *tsc = dev_id; 172 173 cy8ctmg110_touch_pos(tsc); 174 175 return IRQ_HANDLED; 176} 177 178static int cy8ctmg110_probe(struct i2c_client *client, 179 const struct i2c_device_id *id) 180{ 181 const struct cy8ctmg110_pdata *pdata = dev_get_platdata(&client->dev); 182 struct cy8ctmg110 *ts; 183 struct input_dev *input_dev; 184 int err; 185 186 /* No pdata no way forward */ 187 if (pdata == NULL) { 188 dev_err(&client->dev, "no pdata\n"); 189 return -ENODEV; 190 } 191 192 if (!i2c_check_functionality(client->adapter, 193 I2C_FUNC_SMBUS_READ_WORD_DATA)) 194 return -EIO; 195 196 ts = kzalloc(sizeof(struct cy8ctmg110), GFP_KERNEL); 197 input_dev = input_allocate_device(); 198 if (!ts || !input_dev) { 199 err = -ENOMEM; 200 goto err_free_mem; 201 } 202 203 ts->client = client; 204 ts->input = input_dev; 205 ts->reset_pin = pdata->reset_pin; 206 ts->irq_pin = pdata->irq_pin; 207 208 snprintf(ts->phys, sizeof(ts->phys), 209 "%s/input0", dev_name(&client->dev)); 210 211 input_dev->name = CY8CTMG110_DRIVER_NAME " Touchscreen"; 212 input_dev->phys = ts->phys; 213 input_dev->id.bustype = BUS_I2C; 214 input_dev->dev.parent = &client->dev; 215 216 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 217 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 218 219 input_set_abs_params(input_dev, ABS_X, 220 CY8CTMG110_X_MIN, CY8CTMG110_X_MAX, 4, 0); 221 input_set_abs_params(input_dev, ABS_Y, 222 CY8CTMG110_Y_MIN, CY8CTMG110_Y_MAX, 4, 0); 223 224 if (ts->reset_pin) { 225 err = gpio_request(ts->reset_pin, NULL); 226 if (err) { 227 dev_err(&client->dev, 228 "Unable to request GPIO pin %d.\n", 229 ts->reset_pin); 230 goto err_free_mem; 231 } 232 } 233 234 cy8ctmg110_power(ts, true); 235 cy8ctmg110_set_sleepmode(ts, false); 236 237 err = gpio_request(ts->irq_pin, "touch_irq_key"); 238 if (err < 0) { 239 dev_err(&client->dev, 240 "Failed to request GPIO %d, error %d\n", 241 ts->irq_pin, err); 242 goto err_shutoff_device; 243 } 244 245 err = gpio_direction_input(ts->irq_pin); 246 if (err < 0) { 247 dev_err(&client->dev, 248 "Failed to configure input direction for GPIO %d, error %d\n", 249 ts->irq_pin, err); 250 goto err_free_irq_gpio; 251 } 252 253 client->irq = gpio_to_irq(ts->irq_pin); 254 if (client->irq < 0) { 255 err = client->irq; 256 dev_err(&client->dev, 257 "Unable to get irq number for GPIO %d, error %d\n", 258 ts->irq_pin, err); 259 goto err_free_irq_gpio; 260 } 261 262 err = request_threaded_irq(client->irq, NULL, cy8ctmg110_irq_thread, 263 IRQF_TRIGGER_RISING | IRQF_ONESHOT, 264 "touch_reset_key", ts); 265 if (err < 0) { 266 dev_err(&client->dev, 267 "irq %d busy? error %d\n", client->irq, err); 268 goto err_free_irq_gpio; 269 } 270 271 err = input_register_device(input_dev); 272 if (err) 273 goto err_free_irq; 274 275 i2c_set_clientdata(client, ts); 276 device_init_wakeup(&client->dev, 1); 277 return 0; 278 279err_free_irq: 280 free_irq(client->irq, ts); 281err_free_irq_gpio: 282 gpio_free(ts->irq_pin); 283err_shutoff_device: 284 cy8ctmg110_set_sleepmode(ts, true); 285 cy8ctmg110_power(ts, false); 286 if (ts->reset_pin) 287 gpio_free(ts->reset_pin); 288err_free_mem: 289 input_free_device(input_dev); 290 kfree(ts); 291 return err; 292} 293 294static int __maybe_unused cy8ctmg110_suspend(struct device *dev) 295{ 296 struct i2c_client *client = to_i2c_client(dev); 297 struct cy8ctmg110 *ts = i2c_get_clientdata(client); 298 299 if (device_may_wakeup(&client->dev)) 300 enable_irq_wake(client->irq); 301 else { 302 cy8ctmg110_set_sleepmode(ts, true); 303 cy8ctmg110_power(ts, false); 304 } 305 return 0; 306} 307 308static int __maybe_unused cy8ctmg110_resume(struct device *dev) 309{ 310 struct i2c_client *client = to_i2c_client(dev); 311 struct cy8ctmg110 *ts = i2c_get_clientdata(client); 312 313 if (device_may_wakeup(&client->dev)) 314 disable_irq_wake(client->irq); 315 else { 316 cy8ctmg110_power(ts, true); 317 cy8ctmg110_set_sleepmode(ts, false); 318 } 319 return 0; 320} 321 322static SIMPLE_DEV_PM_OPS(cy8ctmg110_pm, cy8ctmg110_suspend, cy8ctmg110_resume); 323 324static int cy8ctmg110_remove(struct i2c_client *client) 325{ 326 struct cy8ctmg110 *ts = i2c_get_clientdata(client); 327 328 cy8ctmg110_set_sleepmode(ts, true); 329 cy8ctmg110_power(ts, false); 330 331 free_irq(client->irq, ts); 332 input_unregister_device(ts->input); 333 gpio_free(ts->irq_pin); 334 if (ts->reset_pin) 335 gpio_free(ts->reset_pin); 336 kfree(ts); 337 338 return 0; 339} 340 341static const struct i2c_device_id cy8ctmg110_idtable[] = { 342 { CY8CTMG110_DRIVER_NAME, 1 }, 343 { } 344}; 345 346MODULE_DEVICE_TABLE(i2c, cy8ctmg110_idtable); 347 348static struct i2c_driver cy8ctmg110_driver = { 349 .driver = { 350 .owner = THIS_MODULE, 351 .name = CY8CTMG110_DRIVER_NAME, 352 .pm = &cy8ctmg110_pm, 353 }, 354 .id_table = cy8ctmg110_idtable, 355 .probe = cy8ctmg110_probe, 356 .remove = cy8ctmg110_remove, 357}; 358 359module_i2c_driver(cy8ctmg110_driver); 360 361MODULE_AUTHOR("Samuli Konttila <samuli.konttila@aavamobile.com>"); 362MODULE_DESCRIPTION("cy8ctmg110 TouchScreen Driver"); 363MODULE_LICENSE("GPL v2"); 364