0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/i2c.h>
0011 #include <linux/input.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/gpio/consumer.h>
0014 #include <linux/kernel.h>
0015 #include <linux/module.h>
0016 #include <linux/slab.h>
0017 #include <asm/byteorder.h>
0018
0019 #define CY8CTMG110_DRIVER_NAME "cy8ctmg110"
0020
0021
0022 #define CY8CTMG110_X_MIN 0
0023 #define CY8CTMG110_Y_MIN 0
0024 #define CY8CTMG110_X_MAX 759
0025 #define CY8CTMG110_Y_MAX 465
0026
0027
0028
0029 #define CY8CTMG110_TOUCH_WAKEUP_TIME 0
0030 #define CY8CTMG110_TOUCH_SLEEP_TIME 2
0031 #define CY8CTMG110_TOUCH_X1 3
0032 #define CY8CTMG110_TOUCH_Y1 5
0033 #define CY8CTMG110_TOUCH_X2 7
0034 #define CY8CTMG110_TOUCH_Y2 9
0035 #define CY8CTMG110_FINGERS 11
0036 #define CY8CTMG110_GESTURE 12
0037 #define CY8CTMG110_REG_MAX 13
0038
0039
0040
0041
0042
0043 struct cy8ctmg110 {
0044 struct input_dev *input;
0045 char phys[32];
0046 struct i2c_client *client;
0047 struct gpio_desc *reset_gpio;
0048 };
0049
0050
0051
0052
0053
0054
0055 static void cy8ctmg110_power(struct cy8ctmg110 *ts, bool poweron)
0056 {
0057 if (ts->reset_gpio)
0058 gpiod_set_value_cansleep(ts->reset_gpio, !poweron);
0059 }
0060
0061 static int cy8ctmg110_write_regs(struct cy8ctmg110 *tsc, unsigned char reg,
0062 unsigned char len, unsigned char *value)
0063 {
0064 struct i2c_client *client = tsc->client;
0065 int ret;
0066 unsigned char i2c_data[6];
0067
0068 BUG_ON(len > 5);
0069
0070 i2c_data[0] = reg;
0071 memcpy(i2c_data + 1, value, len);
0072
0073 ret = i2c_master_send(client, i2c_data, len + 1);
0074 if (ret != len + 1) {
0075 dev_err(&client->dev, "i2c write data cmd failed\n");
0076 return ret < 0 ? ret : -EIO;
0077 }
0078
0079 return 0;
0080 }
0081
0082 static int cy8ctmg110_read_regs(struct cy8ctmg110 *tsc,
0083 unsigned char *data, unsigned char len, unsigned char cmd)
0084 {
0085 struct i2c_client *client = tsc->client;
0086 int ret;
0087 struct i2c_msg msg[2] = {
0088
0089 {
0090 .addr = client->addr,
0091 .len = 1,
0092 .buf = &cmd
0093 },
0094
0095 {
0096 .addr = client->addr,
0097 .flags = I2C_M_RD,
0098 .len = len,
0099 .buf = data
0100 }
0101 };
0102
0103 ret = i2c_transfer(client->adapter, msg, 2);
0104 if (ret < 0)
0105 return ret;
0106
0107 return 0;
0108 }
0109
0110 static int cy8ctmg110_touch_pos(struct cy8ctmg110 *tsc)
0111 {
0112 struct input_dev *input = tsc->input;
0113 unsigned char reg_p[CY8CTMG110_REG_MAX];
0114
0115 memset(reg_p, 0, CY8CTMG110_REG_MAX);
0116
0117
0118 if (cy8ctmg110_read_regs(tsc, reg_p, 9, CY8CTMG110_TOUCH_X1) != 0)
0119 return -EIO;
0120
0121
0122 if (reg_p[8] == 0) {
0123 input_report_key(input, BTN_TOUCH, 0);
0124 } else {
0125 input_report_key(input, BTN_TOUCH, 1);
0126 input_report_abs(input, ABS_X,
0127 be16_to_cpup((__be16 *)(reg_p + 0)));
0128 input_report_abs(input, ABS_Y,
0129 be16_to_cpup((__be16 *)(reg_p + 2)));
0130 }
0131
0132 input_sync(input);
0133
0134 return 0;
0135 }
0136
0137 static int cy8ctmg110_set_sleepmode(struct cy8ctmg110 *ts, bool sleep)
0138 {
0139 unsigned char reg_p[3];
0140
0141 if (sleep) {
0142 reg_p[0] = 0x00;
0143 reg_p[1] = 0xff;
0144 reg_p[2] = 5;
0145 } else {
0146 reg_p[0] = 0x10;
0147 reg_p[1] = 0xff;
0148 reg_p[2] = 0;
0149 }
0150
0151 return cy8ctmg110_write_regs(ts, CY8CTMG110_TOUCH_WAKEUP_TIME, 3, reg_p);
0152 }
0153
0154 static irqreturn_t cy8ctmg110_irq_thread(int irq, void *dev_id)
0155 {
0156 struct cy8ctmg110 *tsc = dev_id;
0157
0158 cy8ctmg110_touch_pos(tsc);
0159
0160 return IRQ_HANDLED;
0161 }
0162
0163 static void cy8ctmg110_shut_off(void *_ts)
0164 {
0165 struct cy8ctmg110 *ts = _ts;
0166
0167 cy8ctmg110_set_sleepmode(ts, true);
0168 cy8ctmg110_power(ts, false);
0169 }
0170
0171 static int cy8ctmg110_probe(struct i2c_client *client,
0172 const struct i2c_device_id *id)
0173 {
0174 struct cy8ctmg110 *ts;
0175 struct input_dev *input_dev;
0176 int err;
0177
0178 if (!i2c_check_functionality(client->adapter,
0179 I2C_FUNC_SMBUS_READ_WORD_DATA))
0180 return -EIO;
0181
0182 ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
0183 if (!ts)
0184 return -ENOMEM;
0185
0186 input_dev = devm_input_allocate_device(&client->dev);
0187 if (!input_dev)
0188 return -ENOMEM;
0189
0190 ts->client = client;
0191 ts->input = input_dev;
0192
0193 snprintf(ts->phys, sizeof(ts->phys),
0194 "%s/input0", dev_name(&client->dev));
0195
0196 input_dev->name = CY8CTMG110_DRIVER_NAME " Touchscreen";
0197 input_dev->phys = ts->phys;
0198 input_dev->id.bustype = BUS_I2C;
0199
0200 input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
0201 input_set_abs_params(input_dev, ABS_X,
0202 CY8CTMG110_X_MIN, CY8CTMG110_X_MAX, 4, 0);
0203 input_set_abs_params(input_dev, ABS_Y,
0204 CY8CTMG110_Y_MIN, CY8CTMG110_Y_MAX, 4, 0);
0205
0206
0207 ts->reset_gpio = devm_gpiod_get_optional(&client->dev, NULL,
0208 GPIOD_OUT_HIGH);
0209 if (IS_ERR(ts->reset_gpio)) {
0210 err = PTR_ERR(ts->reset_gpio);
0211 dev_err(&client->dev,
0212 "Unable to request reset GPIO: %d\n", err);
0213 return err;
0214 }
0215
0216 cy8ctmg110_power(ts, true);
0217 cy8ctmg110_set_sleepmode(ts, false);
0218
0219 err = devm_add_action_or_reset(&client->dev, cy8ctmg110_shut_off, ts);
0220 if (err)
0221 return err;
0222
0223 err = devm_request_threaded_irq(&client->dev, client->irq,
0224 NULL, cy8ctmg110_irq_thread,
0225 IRQF_ONESHOT, "touch_reset_key", ts);
0226 if (err) {
0227 dev_err(&client->dev,
0228 "irq %d busy? error %d\n", client->irq, err);
0229 return err;
0230 }
0231
0232 err = input_register_device(input_dev);
0233 if (err)
0234 return err;
0235
0236 i2c_set_clientdata(client, ts);
0237
0238 return 0;
0239 }
0240
0241 static int __maybe_unused cy8ctmg110_suspend(struct device *dev)
0242 {
0243 struct i2c_client *client = to_i2c_client(dev);
0244 struct cy8ctmg110 *ts = i2c_get_clientdata(client);
0245
0246 if (!device_may_wakeup(&client->dev)) {
0247 cy8ctmg110_set_sleepmode(ts, true);
0248 cy8ctmg110_power(ts, false);
0249 }
0250
0251 return 0;
0252 }
0253
0254 static int __maybe_unused cy8ctmg110_resume(struct device *dev)
0255 {
0256 struct i2c_client *client = to_i2c_client(dev);
0257 struct cy8ctmg110 *ts = i2c_get_clientdata(client);
0258
0259 if (!device_may_wakeup(&client->dev)) {
0260 cy8ctmg110_power(ts, true);
0261 cy8ctmg110_set_sleepmode(ts, false);
0262 }
0263
0264 return 0;
0265 }
0266
0267 static SIMPLE_DEV_PM_OPS(cy8ctmg110_pm, cy8ctmg110_suspend, cy8ctmg110_resume);
0268
0269 static const struct i2c_device_id cy8ctmg110_idtable[] = {
0270 { CY8CTMG110_DRIVER_NAME, 1 },
0271 { }
0272 };
0273
0274 MODULE_DEVICE_TABLE(i2c, cy8ctmg110_idtable);
0275
0276 static struct i2c_driver cy8ctmg110_driver = {
0277 .driver = {
0278 .name = CY8CTMG110_DRIVER_NAME,
0279 .pm = &cy8ctmg110_pm,
0280 },
0281 .id_table = cy8ctmg110_idtable,
0282 .probe = cy8ctmg110_probe,
0283 };
0284
0285 module_i2c_driver(cy8ctmg110_driver);
0286
0287 MODULE_AUTHOR("Samuli Konttila <samuli.konttila@aavamobile.com>");
0288 MODULE_DESCRIPTION("cy8ctmg110 TouchScreen Driver");
0289 MODULE_LICENSE("GPL v2");