Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.7-rc4 625 lines 14 kB view raw
1/* 2 * Core Source for: 3 * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers. 4 * For use with Cypress Txx3xx parts. 5 * Supported parts include: 6 * CY8CTST341 7 * CY8CTMA340 8 * 9 * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. 10 * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * version 2, and only version 2, as published by the 15 * Free Software Foundation. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License along 23 * with this program; if not, write to the Free Software Foundation, Inc., 24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 25 * 26 * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com> 27 * 28 */ 29 30#include <linux/delay.h> 31#include <linux/input.h> 32#include <linux/input/mt.h> 33#include <linux/gpio.h> 34#include <linux/interrupt.h> 35#include <linux/slab.h> 36 37#include "cyttsp_core.h" 38 39/* Bootloader number of command keys */ 40#define CY_NUM_BL_KEYS 8 41 42/* helpers */ 43#define GET_NUM_TOUCHES(x) ((x) & 0x0F) 44#define IS_LARGE_AREA(x) (((x) & 0x10) >> 4) 45#define IS_BAD_PKT(x) ((x) & 0x20) 46#define IS_VALID_APP(x) ((x) & 0x01) 47#define IS_OPERATIONAL_ERR(x) ((x) & 0x3F) 48#define GET_HSTMODE(reg) (((reg) & 0x70) >> 4) 49#define GET_BOOTLOADERMODE(reg) (((reg) & 0x10) >> 4) 50 51#define CY_REG_BASE 0x00 52#define CY_REG_ACT_DIST 0x1E 53#define CY_REG_ACT_INTRVL 0x1D 54#define CY_REG_TCH_TMOUT (CY_REG_ACT_INTRVL + 1) 55#define CY_REG_LP_INTRVL (CY_REG_TCH_TMOUT + 1) 56#define CY_MAXZ 255 57#define CY_DELAY_DFLT 20 /* ms */ 58#define CY_DELAY_MAX 500 59#define CY_ACT_DIST_DFLT 0xF8 60#define CY_HNDSHK_BIT 0x80 61/* device mode bits */ 62#define CY_OPERATE_MODE 0x00 63#define CY_SYSINFO_MODE 0x10 64/* power mode select bits */ 65#define CY_SOFT_RESET_MODE 0x01 /* return to Bootloader mode */ 66#define CY_DEEP_SLEEP_MODE 0x02 67#define CY_LOW_POWER_MODE 0x04 68 69/* Slots management */ 70#define CY_MAX_FINGER 4 71#define CY_MAX_ID 16 72 73static const u8 bl_command[] = { 74 0x00, /* file offset */ 75 0xFF, /* command */ 76 0xA5, /* exit bootloader command */ 77 0, 1, 2, 3, 4, 5, 6, 7 /* default keys */ 78}; 79 80static int ttsp_read_block_data(struct cyttsp *ts, u8 command, 81 u8 length, void *buf) 82{ 83 int error; 84 int tries; 85 86 for (tries = 0; tries < CY_NUM_RETRY; tries++) { 87 error = ts->bus_ops->read(ts, command, length, buf); 88 if (!error) 89 return 0; 90 91 msleep(CY_DELAY_DFLT); 92 } 93 94 return -EIO; 95} 96 97static int ttsp_write_block_data(struct cyttsp *ts, u8 command, 98 u8 length, void *buf) 99{ 100 int error; 101 int tries; 102 103 for (tries = 0; tries < CY_NUM_RETRY; tries++) { 104 error = ts->bus_ops->write(ts, command, length, buf); 105 if (!error) 106 return 0; 107 108 msleep(CY_DELAY_DFLT); 109 } 110 111 return -EIO; 112} 113 114static int ttsp_send_command(struct cyttsp *ts, u8 cmd) 115{ 116 return ttsp_write_block_data(ts, CY_REG_BASE, sizeof(cmd), &cmd); 117} 118 119static int cyttsp_load_bl_regs(struct cyttsp *ts) 120{ 121 memset(&ts->bl_data, 0, sizeof(ts->bl_data)); 122 ts->bl_data.bl_status = 0x10; 123 124 return ttsp_read_block_data(ts, CY_REG_BASE, 125 sizeof(ts->bl_data), &ts->bl_data); 126} 127 128static int cyttsp_exit_bl_mode(struct cyttsp *ts) 129{ 130 int error; 131 u8 bl_cmd[sizeof(bl_command)]; 132 133 memcpy(bl_cmd, bl_command, sizeof(bl_command)); 134 if (ts->pdata->bl_keys) 135 memcpy(&bl_cmd[sizeof(bl_command) - CY_NUM_BL_KEYS], 136 ts->pdata->bl_keys, sizeof(bl_command)); 137 138 error = ttsp_write_block_data(ts, CY_REG_BASE, 139 sizeof(bl_cmd), bl_cmd); 140 if (error) 141 return error; 142 143 /* wait for TTSP Device to complete the operation */ 144 msleep(CY_DELAY_DFLT); 145 146 error = cyttsp_load_bl_regs(ts); 147 if (error) 148 return error; 149 150 if (GET_BOOTLOADERMODE(ts->bl_data.bl_status)) 151 return -EIO; 152 153 return 0; 154} 155 156static int cyttsp_set_operational_mode(struct cyttsp *ts) 157{ 158 int error; 159 160 error = ttsp_send_command(ts, CY_OPERATE_MODE); 161 if (error) 162 return error; 163 164 /* wait for TTSP Device to complete switch to Operational mode */ 165 error = ttsp_read_block_data(ts, CY_REG_BASE, 166 sizeof(ts->xy_data), &ts->xy_data); 167 if (error) 168 return error; 169 170 return ts->xy_data.act_dist == CY_ACT_DIST_DFLT ? -EIO : 0; 171} 172 173static int cyttsp_set_sysinfo_mode(struct cyttsp *ts) 174{ 175 int error; 176 177 memset(&ts->sysinfo_data, 0, sizeof(ts->sysinfo_data)); 178 179 /* switch to sysinfo mode */ 180 error = ttsp_send_command(ts, CY_SYSINFO_MODE); 181 if (error) 182 return error; 183 184 /* read sysinfo registers */ 185 msleep(CY_DELAY_DFLT); 186 error = ttsp_read_block_data(ts, CY_REG_BASE, sizeof(ts->sysinfo_data), 187 &ts->sysinfo_data); 188 if (error) 189 return error; 190 191 if (!ts->sysinfo_data.tts_verh && !ts->sysinfo_data.tts_verl) 192 return -EIO; 193 194 return 0; 195} 196 197static int cyttsp_set_sysinfo_regs(struct cyttsp *ts) 198{ 199 int retval = 0; 200 201 if (ts->pdata->act_intrvl != CY_ACT_INTRVL_DFLT || 202 ts->pdata->tch_tmout != CY_TCH_TMOUT_DFLT || 203 ts->pdata->lp_intrvl != CY_LP_INTRVL_DFLT) { 204 205 u8 intrvl_ray[] = { 206 ts->pdata->act_intrvl, 207 ts->pdata->tch_tmout, 208 ts->pdata->lp_intrvl 209 }; 210 211 /* set intrvl registers */ 212 retval = ttsp_write_block_data(ts, CY_REG_ACT_INTRVL, 213 sizeof(intrvl_ray), intrvl_ray); 214 msleep(CY_DELAY_DFLT); 215 } 216 217 return retval; 218} 219 220static int cyttsp_soft_reset(struct cyttsp *ts) 221{ 222 unsigned long timeout; 223 int retval; 224 225 /* wait for interrupt to set ready completion */ 226 INIT_COMPLETION(ts->bl_ready); 227 ts->state = CY_BL_STATE; 228 229 enable_irq(ts->irq); 230 231 retval = ttsp_send_command(ts, CY_SOFT_RESET_MODE); 232 if (retval) 233 goto out; 234 235 timeout = wait_for_completion_timeout(&ts->bl_ready, 236 msecs_to_jiffies(CY_DELAY_DFLT * CY_DELAY_MAX)); 237 retval = timeout ? 0 : -EIO; 238 239out: 240 ts->state = CY_IDLE_STATE; 241 disable_irq(ts->irq); 242 return retval; 243} 244 245static int cyttsp_act_dist_setup(struct cyttsp *ts) 246{ 247 u8 act_dist_setup = ts->pdata->act_dist; 248 249 /* Init gesture; active distance setup */ 250 return ttsp_write_block_data(ts, CY_REG_ACT_DIST, 251 sizeof(act_dist_setup), &act_dist_setup); 252} 253 254static void cyttsp_extract_track_ids(struct cyttsp_xydata *xy_data, int *ids) 255{ 256 ids[0] = xy_data->touch12_id >> 4; 257 ids[1] = xy_data->touch12_id & 0xF; 258 ids[2] = xy_data->touch34_id >> 4; 259 ids[3] = xy_data->touch34_id & 0xF; 260} 261 262static const struct cyttsp_tch *cyttsp_get_tch(struct cyttsp_xydata *xy_data, 263 int idx) 264{ 265 switch (idx) { 266 case 0: 267 return &xy_data->tch1; 268 case 1: 269 return &xy_data->tch2; 270 case 2: 271 return &xy_data->tch3; 272 case 3: 273 return &xy_data->tch4; 274 default: 275 return NULL; 276 } 277} 278 279static void cyttsp_report_tchdata(struct cyttsp *ts) 280{ 281 struct cyttsp_xydata *xy_data = &ts->xy_data; 282 struct input_dev *input = ts->input; 283 int num_tch = GET_NUM_TOUCHES(xy_data->tt_stat); 284 const struct cyttsp_tch *tch; 285 int ids[CY_MAX_ID]; 286 int i; 287 DECLARE_BITMAP(used, CY_MAX_ID); 288 289 if (IS_LARGE_AREA(xy_data->tt_stat) == 1) { 290 /* terminate all active tracks */ 291 num_tch = 0; 292 dev_dbg(ts->dev, "%s: Large area detected\n", __func__); 293 } else if (num_tch > CY_MAX_FINGER) { 294 /* terminate all active tracks */ 295 num_tch = 0; 296 dev_dbg(ts->dev, "%s: Num touch error detected\n", __func__); 297 } else if (IS_BAD_PKT(xy_data->tt_mode)) { 298 /* terminate all active tracks */ 299 num_tch = 0; 300 dev_dbg(ts->dev, "%s: Invalid buffer detected\n", __func__); 301 } 302 303 cyttsp_extract_track_ids(xy_data, ids); 304 305 bitmap_zero(used, CY_MAX_ID); 306 307 for (i = 0; i < num_tch; i++) { 308 tch = cyttsp_get_tch(xy_data, i); 309 310 input_mt_slot(input, ids[i]); 311 input_mt_report_slot_state(input, MT_TOOL_FINGER, true); 312 input_report_abs(input, ABS_MT_POSITION_X, be16_to_cpu(tch->x)); 313 input_report_abs(input, ABS_MT_POSITION_Y, be16_to_cpu(tch->y)); 314 input_report_abs(input, ABS_MT_TOUCH_MAJOR, tch->z); 315 316 __set_bit(ids[i], used); 317 } 318 319 for (i = 0; i < CY_MAX_ID; i++) { 320 if (test_bit(i, used)) 321 continue; 322 323 input_mt_slot(input, i); 324 input_mt_report_slot_state(input, MT_TOOL_FINGER, false); 325 } 326 327 input_sync(input); 328} 329 330static irqreturn_t cyttsp_irq(int irq, void *handle) 331{ 332 struct cyttsp *ts = handle; 333 int error; 334 335 if (unlikely(ts->state == CY_BL_STATE)) { 336 complete(&ts->bl_ready); 337 goto out; 338 } 339 340 /* Get touch data from CYTTSP device */ 341 error = ttsp_read_block_data(ts, CY_REG_BASE, 342 sizeof(struct cyttsp_xydata), &ts->xy_data); 343 if (error) 344 goto out; 345 346 /* provide flow control handshake */ 347 if (ts->pdata->use_hndshk) { 348 error = ttsp_send_command(ts, 349 ts->xy_data.hst_mode ^ CY_HNDSHK_BIT); 350 if (error) 351 goto out; 352 } 353 354 if (unlikely(ts->state == CY_IDLE_STATE)) 355 goto out; 356 357 if (GET_BOOTLOADERMODE(ts->xy_data.tt_mode)) { 358 /* 359 * TTSP device has reset back to bootloader mode. 360 * Restore to operational mode. 361 */ 362 error = cyttsp_exit_bl_mode(ts); 363 if (error) { 364 dev_err(ts->dev, 365 "Could not return to operational mode, err: %d\n", 366 error); 367 ts->state = CY_IDLE_STATE; 368 } 369 } else { 370 cyttsp_report_tchdata(ts); 371 } 372 373out: 374 return IRQ_HANDLED; 375} 376 377static int cyttsp_power_on(struct cyttsp *ts) 378{ 379 int error; 380 381 error = cyttsp_soft_reset(ts); 382 if (error) 383 return error; 384 385 error = cyttsp_load_bl_regs(ts); 386 if (error) 387 return error; 388 389 if (GET_BOOTLOADERMODE(ts->bl_data.bl_status) && 390 IS_VALID_APP(ts->bl_data.bl_status)) { 391 error = cyttsp_exit_bl_mode(ts); 392 if (error) 393 return error; 394 } 395 396 if (GET_HSTMODE(ts->bl_data.bl_file) != CY_OPERATE_MODE || 397 IS_OPERATIONAL_ERR(ts->bl_data.bl_status)) { 398 return -ENODEV; 399 } 400 401 error = cyttsp_set_sysinfo_mode(ts); 402 if (error) 403 return error; 404 405 error = cyttsp_set_sysinfo_regs(ts); 406 if (error) 407 return error; 408 409 error = cyttsp_set_operational_mode(ts); 410 if (error) 411 return error; 412 413 /* init active distance */ 414 error = cyttsp_act_dist_setup(ts); 415 if (error) 416 return error; 417 418 ts->state = CY_ACTIVE_STATE; 419 420 return 0; 421} 422 423static int cyttsp_enable(struct cyttsp *ts) 424{ 425 int error; 426 427 /* 428 * The device firmware can wake on an I2C or SPI memory slave 429 * address match. So just reading a register is sufficient to 430 * wake up the device. The first read attempt will fail but it 431 * will wake it up making the second read attempt successful. 432 */ 433 error = ttsp_read_block_data(ts, CY_REG_BASE, 434 sizeof(ts->xy_data), &ts->xy_data); 435 if (error) 436 return error; 437 438 if (GET_HSTMODE(ts->xy_data.hst_mode)) 439 return -EIO; 440 441 enable_irq(ts->irq); 442 443 return 0; 444} 445 446static int cyttsp_disable(struct cyttsp *ts) 447{ 448 int error; 449 450 error = ttsp_send_command(ts, CY_LOW_POWER_MODE); 451 if (error) 452 return error; 453 454 disable_irq(ts->irq); 455 456 return 0; 457} 458 459#ifdef CONFIG_PM_SLEEP 460static int cyttsp_suspend(struct device *dev) 461{ 462 struct cyttsp *ts = dev_get_drvdata(dev); 463 int retval = 0; 464 465 mutex_lock(&ts->input->mutex); 466 467 if (ts->input->users) { 468 retval = cyttsp_disable(ts); 469 if (retval == 0) 470 ts->suspended = true; 471 } 472 473 mutex_unlock(&ts->input->mutex); 474 475 return retval; 476} 477 478static int cyttsp_resume(struct device *dev) 479{ 480 struct cyttsp *ts = dev_get_drvdata(dev); 481 482 mutex_lock(&ts->input->mutex); 483 484 if (ts->input->users) 485 cyttsp_enable(ts); 486 487 ts->suspended = false; 488 489 mutex_unlock(&ts->input->mutex); 490 491 return 0; 492} 493 494#endif 495 496SIMPLE_DEV_PM_OPS(cyttsp_pm_ops, cyttsp_suspend, cyttsp_resume); 497EXPORT_SYMBOL_GPL(cyttsp_pm_ops); 498 499static int cyttsp_open(struct input_dev *dev) 500{ 501 struct cyttsp *ts = input_get_drvdata(dev); 502 int retval = 0; 503 504 if (!ts->suspended) 505 retval = cyttsp_enable(ts); 506 507 return retval; 508} 509 510static void cyttsp_close(struct input_dev *dev) 511{ 512 struct cyttsp *ts = input_get_drvdata(dev); 513 514 if (!ts->suspended) 515 cyttsp_disable(ts); 516} 517 518struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, 519 struct device *dev, int irq, size_t xfer_buf_size) 520{ 521 const struct cyttsp_platform_data *pdata = dev->platform_data; 522 struct cyttsp *ts; 523 struct input_dev *input_dev; 524 int error; 525 526 if (!pdata || !pdata->name || irq <= 0) { 527 error = -EINVAL; 528 goto err_out; 529 } 530 531 ts = kzalloc(sizeof(*ts) + xfer_buf_size, GFP_KERNEL); 532 input_dev = input_allocate_device(); 533 if (!ts || !input_dev) { 534 error = -ENOMEM; 535 goto err_free_mem; 536 } 537 538 ts->dev = dev; 539 ts->input = input_dev; 540 ts->pdata = dev->platform_data; 541 ts->bus_ops = bus_ops; 542 ts->irq = irq; 543 544 init_completion(&ts->bl_ready); 545 snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev)); 546 547 if (pdata->init) { 548 error = pdata->init(); 549 if (error) { 550 dev_err(ts->dev, "platform init failed, err: %d\n", 551 error); 552 goto err_free_mem; 553 } 554 } 555 556 input_dev->name = pdata->name; 557 input_dev->phys = ts->phys; 558 input_dev->id.bustype = bus_ops->bustype; 559 input_dev->dev.parent = ts->dev; 560 561 input_dev->open = cyttsp_open; 562 input_dev->close = cyttsp_close; 563 564 input_set_drvdata(input_dev, ts); 565 566 __set_bit(EV_ABS, input_dev->evbit); 567 input_set_abs_params(input_dev, ABS_MT_POSITION_X, 568 0, pdata->maxx, 0, 0); 569 input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 570 0, pdata->maxy, 0, 0); 571 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 572 0, CY_MAXZ, 0, 0); 573 574 input_mt_init_slots(input_dev, CY_MAX_ID, 0); 575 576 error = request_threaded_irq(ts->irq, NULL, cyttsp_irq, 577 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 578 pdata->name, ts); 579 if (error) { 580 dev_err(ts->dev, "failed to request IRQ %d, err: %d\n", 581 ts->irq, error); 582 goto err_platform_exit; 583 } 584 585 disable_irq(ts->irq); 586 587 error = cyttsp_power_on(ts); 588 if (error) 589 goto err_free_irq; 590 591 error = input_register_device(input_dev); 592 if (error) { 593 dev_err(ts->dev, "failed to register input device: %d\n", 594 error); 595 goto err_free_irq; 596 } 597 598 return ts; 599 600err_free_irq: 601 free_irq(ts->irq, ts); 602err_platform_exit: 603 if (pdata->exit) 604 pdata->exit(); 605err_free_mem: 606 input_free_device(input_dev); 607 kfree(ts); 608err_out: 609 return ERR_PTR(error); 610} 611EXPORT_SYMBOL_GPL(cyttsp_probe); 612 613void cyttsp_remove(struct cyttsp *ts) 614{ 615 free_irq(ts->irq, ts); 616 input_unregister_device(ts->input); 617 if (ts->pdata->exit) 618 ts->pdata->exit(); 619 kfree(ts); 620} 621EXPORT_SYMBOL_GPL(cyttsp_remove); 622 623MODULE_LICENSE("GPL"); 624MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard touchscreen driver core"); 625MODULE_AUTHOR("Cypress");