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