linux/drivers/staging/dream/synaptics_i2c_rmi.c
<<
>>
Prefs
   1/*
   2 * Support for synaptics touchscreen.
   3 *
   4 * Copyright (C) 2007 Google, Inc.
   5 * Author: Arve Hjønnevåg <arve@android.com>
   6 *
   7 * This software is licensed under the terms of the GNU General Public
   8 * License version 2, as published by the Free Software Foundation, and
   9 * may be copied, distributed, and modified under those terms.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * http://www.synaptics.com/sites/default/files/511_000099_01F.pdf
  17 */
  18
  19#include <linux/module.h>
  20#include <linux/delay.h>
  21#include <linux/slab.h>
  22#ifdef CONFIG_HAS_EARLYSUSPEND
  23#include <linux/earlysuspend.h>
  24#endif
  25#include <linux/hrtimer.h>
  26#include <linux/i2c.h>
  27#include <linux/input.h>
  28#include <linux/interrupt.h>
  29#include <linux/io.h>
  30#include <linux/platform_device.h>
  31#include "synaptics_i2c_rmi.h"
  32
  33static struct workqueue_struct *synaptics_wq;
  34
  35struct synaptics_ts_data {
  36        u16 addr;
  37        struct i2c_client *client;
  38        struct input_dev *input_dev;
  39        int use_irq;
  40        struct hrtimer timer;
  41        struct work_struct  work;
  42        u16 max[2];
  43        int snap_state[2][2];
  44        int snap_down_on[2];
  45        int snap_down_off[2];
  46        int snap_up_on[2];
  47        int snap_up_off[2];
  48        int snap_down[2];
  49        int snap_up[2];
  50        u32 flags;
  51        int (*power)(int on);
  52#ifdef CONFIG_HAS_EARLYSUSPEND
  53        struct early_suspend early_suspend;
  54#endif
  55};
  56
  57static int i2c_set(struct synaptics_ts_data *ts, u8 reg, u8 val, char *msg)
  58{
  59        int ret = i2c_smbus_write_byte_data(ts->client, reg, val);
  60        if (ret < 0)
  61                pr_err("i2c_smbus_write_byte_data failed (%s)\n", msg);
  62        return ret;
  63}
  64
  65static int i2c_read(struct synaptics_ts_data *ts, u8 reg, char *msg)
  66{
  67        int ret = i2c_smbus_read_byte_data(ts->client, reg);
  68        if (ret < 0)
  69                pr_err("i2c_smbus_read_byte_data failed (%s)\n", msg);
  70        return ret;
  71}
  72#ifdef CONFIG_HAS_EARLYSUSPEND
  73static void synaptics_ts_early_suspend(struct early_suspend *h);
  74static void synaptics_ts_late_resume(struct early_suspend *h);
  75#endif
  76
  77static int synaptics_init_panel(struct synaptics_ts_data *ts)
  78{
  79        int ret;
  80
  81        ret = i2c_set(ts, 0xff, 0x10, "set page select");
  82        if (ret == 0)
  83                ret = i2c_set(ts, 0x41, 0x04, "set No Clip Z");
  84
  85        ret = i2c_set(ts, 0xff, 0x04, "fallback page select");
  86        ret = i2c_set(ts, 0xf0, 0x81, "select 80 reports per second");
  87        return ret;
  88}
  89
  90static void decode_report(struct synaptics_ts_data *ts, u8 *buf)
  91{
  92/*
  93 * This sensor sends two 6-byte absolute finger reports, an optional
  94 * 2-byte relative report followed by a status byte. This function
  95 * reads the two finger reports and transforms the coordinates
  96 * according the platform data so they can be aligned with the lcd
  97 * behind the touchscreen. Typically we flip the y-axis since the
  98 * sensor uses the bottom left corner as the origin, but if the sensor
  99 * is mounted upside down the platform data will request that the
 100 * x-axis should be flipped instead. The snap to inactive edge border
 101 * are used to allow tapping the edges of the screen on the G1. The
 102 * active area of the touchscreen is smaller than the lcd. When the
 103 * finger gets close the edge of the screen we snap it to the
 104 * edge. This allows ui elements at the edge of the screen to be hit,
 105 * and it prevents hitting ui elements that are not at the edge of the
 106 * screen when the finger is touching the edge.
 107 */
 108        int pos[2][2];
 109        int f, a;
 110        int base = 2;
 111        int z = buf[1];
 112        int finger = buf[0] & 7;
 113
 114        for (f = 0; f < 2; f++) {
 115                u32 flip_flag = SYNAPTICS_FLIP_X;
 116                for (a = 0; a < 2; a++) {
 117                        int p = buf[base + 1];
 118                        p |= (u16)(buf[base] & 0x1f) << 8;
 119                        if (ts->flags & flip_flag)
 120                                p = ts->max[a] - p;
 121                        if (ts->flags & SYNAPTICS_SNAP_TO_INACTIVE_EDGE) {
 122                                if (ts->snap_state[f][a]) {
 123                                        if (p <= ts->snap_down_off[a])
 124                                                p = ts->snap_down[a];
 125                                        else if (p >= ts->snap_up_off[a])
 126                                                p = ts->snap_up[a];
 127                                        else
 128                                                ts->snap_state[f][a] = 0;
 129                                } else {
 130                                        if (p <= ts->snap_down_on[a]) {
 131                                                p = ts->snap_down[a];
 132                                                ts->snap_state[f][a] = 1;
 133                                        } else if (p >= ts->snap_up_on[a]) {
 134                                                p = ts->snap_up[a];
 135                                                ts->snap_state[f][a] = 1;
 136                                        }
 137                                }
 138                        }
 139                        pos[f][a] = p;
 140                        base += 2;
 141                        flip_flag <<= 1;
 142                }
 143                base += 2;
 144                if (ts->flags & SYNAPTICS_SWAP_XY)
 145                        swap(pos[f][0], pos[f][1]);
 146        }
 147        if (z) {
 148                input_report_abs(ts->input_dev, ABS_X, pos[0][0]);
 149                input_report_abs(ts->input_dev, ABS_Y, pos[0][1]);
 150        }
 151        input_report_abs(ts->input_dev, ABS_PRESSURE, z);
 152        input_report_key(ts->input_dev, BTN_TOUCH, finger);
 153        input_sync(ts->input_dev);
 154}
 155
 156static void synaptics_ts_work_func(struct work_struct *work)
 157{
 158        int i;
 159        int ret;
 160        int bad_data = 0;
 161        struct i2c_msg msg[2];
 162        u8 start_reg = 0;
 163        u8 buf[15];
 164        struct synaptics_ts_data *ts =
 165                container_of(work, struct synaptics_ts_data, work);
 166
 167        msg[0].addr = ts->client->addr;
 168        msg[0].flags = 0;
 169        msg[0].len = 1;
 170        msg[0].buf = &start_reg;
 171        msg[1].addr = ts->client->addr;
 172        msg[1].flags = I2C_M_RD;
 173        msg[1].len = sizeof(buf);
 174        msg[1].buf = buf;
 175
 176        for (i = 0; i < ((ts->use_irq && !bad_data) ? 1 : 10); i++) {
 177                ret = i2c_transfer(ts->client->adapter, msg, 2);
 178                if (ret < 0) {
 179                        pr_err("ts_work: i2c_transfer failed\n");
 180                        bad_data = 1;
 181                        continue;
 182                }
 183                if ((buf[14] & 0xc0) != 0x40) {
 184                        pr_warning("synaptics_ts_work_func:"
 185                               " bad read %x %x %x %x %x %x %x %x %x"
 186                               " %x %x %x %x %x %x, ret %d\n",
 187                               buf[0], buf[1], buf[2], buf[3],
 188                               buf[4], buf[5], buf[6], buf[7],
 189                               buf[8], buf[9], buf[10], buf[11],
 190                               buf[12], buf[13], buf[14], ret);
 191                        if (bad_data)
 192                                synaptics_init_panel(ts);
 193                        bad_data = 1;
 194                        continue;
 195                }
 196                bad_data = 0;
 197                if ((buf[14] & 1) == 0)
 198                        break;
 199
 200                decode_report(ts, buf);
 201        }
 202}
 203
 204static enum hrtimer_restart synaptics_ts_timer_func(struct hrtimer *timer)
 205{
 206        struct synaptics_ts_data *ts =
 207                container_of(timer, struct synaptics_ts_data, timer);
 208
 209        queue_work(synaptics_wq, &ts->work);
 210
 211        hrtimer_start(&ts->timer, ktime_set(0, 12500000), HRTIMER_MODE_REL);
 212        return HRTIMER_NORESTART;
 213}
 214
 215static irqreturn_t synaptics_ts_irq_handler(int irq, void *dev_id)
 216{
 217        struct synaptics_ts_data *ts = dev_id;
 218
 219        synaptics_ts_work_func(&ts->work);
 220        return IRQ_HANDLED;
 221}
 222
 223static int detect(struct synaptics_ts_data *ts, u32 *panel_version)
 224{
 225        int ret;
 226        int retry = 10;
 227
 228        ret = i2c_set(ts, 0xf4, 0x01, "reset device");
 229
 230        while (retry-- > 0) {
 231                ret = i2c_smbus_read_byte_data(ts->client, 0xe4);
 232                if (ret >= 0)
 233                        break;
 234                msleep(100);
 235        }
 236        if (ret < 0) {
 237                pr_err("i2c_smbus_read_byte_data failed\n");
 238                return ret;
 239        }
 240
 241        *panel_version = ret << 8;
 242        ret = i2c_read(ts, 0xe5, "product minor");
 243        if (ret < 0)
 244                return ret;
 245        *panel_version |= ret;
 246
 247        ret = i2c_read(ts, 0xe3, "property");
 248        if (ret < 0)
 249                return ret;
 250
 251        pr_info("synaptics: version %x, product property %x\n",
 252                *panel_version, ret);
 253        return 0;
 254}
 255
 256static void compute_areas(struct synaptics_ts_data *ts,
 257                          struct synaptics_i2c_rmi_platform_data *pdata,
 258                          u16 max_x, u16 max_y)
 259{
 260        int inactive_area_left;
 261        int inactive_area_right;
 262        int inactive_area_top;
 263        int inactive_area_bottom;
 264        int snap_left_on;
 265        int snap_left_off;
 266        int snap_right_on;
 267        int snap_right_off;
 268        int snap_top_on;
 269        int snap_top_off;
 270        int snap_bottom_on;
 271        int snap_bottom_off;
 272        int fuzz_x;
 273        int fuzz_y;
 274        int fuzz_p;
 275        int fuzz_w;
 276        int swapped = !!(ts->flags & SYNAPTICS_SWAP_XY);
 277
 278        inactive_area_left = pdata->inactive_left;
 279        inactive_area_right = pdata->inactive_right;
 280        inactive_area_top = pdata->inactive_top;
 281        inactive_area_bottom = pdata->inactive_bottom;
 282        snap_left_on = pdata->snap_left_on;
 283        snap_left_off = pdata->snap_left_off;
 284        snap_right_on = pdata->snap_right_on;
 285        snap_right_off = pdata->snap_right_off;
 286        snap_top_on = pdata->snap_top_on;
 287        snap_top_off = pdata->snap_top_off;
 288        snap_bottom_on = pdata->snap_bottom_on;
 289        snap_bottom_off = pdata->snap_bottom_off;
 290        fuzz_x = pdata->fuzz_x;
 291        fuzz_y = pdata->fuzz_y;
 292        fuzz_p = pdata->fuzz_p;
 293        fuzz_w = pdata->fuzz_w;
 294
 295        inactive_area_left = inactive_area_left * max_x / 0x10000;
 296        inactive_area_right = inactive_area_right * max_x / 0x10000;
 297        inactive_area_top = inactive_area_top * max_y / 0x10000;
 298        inactive_area_bottom = inactive_area_bottom * max_y / 0x10000;
 299        snap_left_on = snap_left_on * max_x / 0x10000;
 300        snap_left_off = snap_left_off * max_x / 0x10000;
 301        snap_right_on = snap_right_on * max_x / 0x10000;
 302        snap_right_off = snap_right_off * max_x / 0x10000;
 303        snap_top_on = snap_top_on * max_y / 0x10000;
 304        snap_top_off = snap_top_off * max_y / 0x10000;
 305        snap_bottom_on = snap_bottom_on * max_y / 0x10000;
 306        snap_bottom_off = snap_bottom_off * max_y / 0x10000;
 307        fuzz_x = fuzz_x * max_x / 0x10000;
 308        fuzz_y = fuzz_y * max_y / 0x10000;
 309
 310
 311        ts->snap_down[swapped] = -inactive_area_left;
 312        ts->snap_up[swapped] = max_x + inactive_area_right;
 313        ts->snap_down[!swapped] = -inactive_area_top;
 314        ts->snap_up[!swapped] = max_y + inactive_area_bottom;
 315        ts->snap_down_on[swapped] = snap_left_on;
 316        ts->snap_down_off[swapped] = snap_left_off;
 317        ts->snap_up_on[swapped] = max_x - snap_right_on;
 318        ts->snap_up_off[swapped] = max_x - snap_right_off;
 319        ts->snap_down_on[!swapped] = snap_top_on;
 320        ts->snap_down_off[!swapped] = snap_top_off;
 321        ts->snap_up_on[!swapped] = max_y - snap_bottom_on;
 322        ts->snap_up_off[!swapped] = max_y - snap_bottom_off;
 323        pr_info("synaptics_ts_probe: max_x %d, max_y %d\n", max_x, max_y);
 324        pr_info("synaptics_ts_probe: inactive_x %d %d, inactive_y %d %d\n",
 325               inactive_area_left, inactive_area_right,
 326               inactive_area_top, inactive_area_bottom);
 327        pr_info("synaptics_ts_probe: snap_x %d-%d %d-%d, snap_y %d-%d %d-%d\n",
 328               snap_left_on, snap_left_off, snap_right_on, snap_right_off,
 329               snap_top_on, snap_top_off, snap_bottom_on, snap_bottom_off);
 330
 331        input_set_abs_params(ts->input_dev, ABS_X,
 332                             -inactive_area_left, max_x + inactive_area_right,
 333                             fuzz_x, 0);
 334        input_set_abs_params(ts->input_dev, ABS_Y,
 335                             -inactive_area_top, max_y + inactive_area_bottom,
 336                             fuzz_y, 0);
 337        input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 255, fuzz_p, 0);
 338}
 339
 340static struct synaptics_i2c_rmi_platform_data fake_pdata;
 341
 342static int __devinit synaptics_ts_probe(
 343        struct i2c_client *client, const struct i2c_device_id *id)
 344{
 345        struct synaptics_ts_data *ts;
 346        u8 buf0[4];
 347        u8 buf1[8];
 348        struct i2c_msg msg[2];
 349        int ret = 0;
 350        struct synaptics_i2c_rmi_platform_data *pdata;
 351        u32 panel_version = 0;
 352        u16 max_x, max_y;
 353
 354        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 355                pr_err("synaptics_ts_probe: need I2C_FUNC_I2C\n");
 356                ret = -ENODEV;
 357                goto err_check_functionality_failed;
 358        }
 359
 360        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
 361                pr_err("synaptics_ts_probe: need I2C_FUNC_SMBUS_WORD_DATA\n");
 362                ret = -ENODEV;
 363                goto err_check_functionality_failed;
 364        }
 365
 366        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
 367                pr_err("synaptics_ts_probe: need I2C_FUNC_SMBUS_WORD_DATA\n");
 368                ret = -ENODEV;
 369                goto err_check_functionality_failed;
 370        }
 371
 372        ts = kzalloc(sizeof(*ts), GFP_KERNEL);
 373        if (ts == NULL) {
 374                ret = -ENOMEM;
 375                goto err_alloc_data_failed;
 376        }
 377        INIT_WORK(&ts->work, synaptics_ts_work_func);
 378        ts->client = client;
 379        i2c_set_clientdata(client, ts);
 380        pdata = client->dev.platform_data;
 381        if (pdata)
 382                ts->power = pdata->power;
 383        else
 384                pdata = &fake_pdata;
 385
 386        if (ts->power) {
 387                ret = ts->power(1);
 388                if (ret < 0) {
 389                        pr_err("synaptics_ts_probe power on failed\n");
 390                        goto err_power_failed;
 391                }
 392        }
 393
 394        ret = detect(ts, &panel_version);
 395        if (ret)
 396                goto err_detect_failed;
 397
 398        while (pdata->version > panel_version)
 399                pdata++;
 400        ts->flags = pdata->flags;
 401
 402        ret = i2c_read(ts, 0xf0, "device control");
 403        if (ret < 0)
 404                goto err_detect_failed;
 405        pr_info("synaptics: device control %x\n", ret);
 406
 407        ret = i2c_read(ts, 0xf1, "interrupt enable");
 408        if (ret < 0)
 409                goto err_detect_failed;
 410        pr_info("synaptics_ts_probe: interrupt enable %x\n", ret);
 411
 412        ret = i2c_set(ts, 0xf1, 0, "disable interrupt");
 413        if (ret < 0)
 414                goto err_detect_failed;
 415
 416        msg[0].addr = ts->client->addr;
 417        msg[0].flags = 0;
 418        msg[0].len = 1;
 419        msg[0].buf = buf0;
 420        buf0[0] = 0xe0;
 421        msg[1].addr = ts->client->addr;
 422        msg[1].flags = I2C_M_RD;
 423        msg[1].len = 8;
 424        msg[1].buf = buf1;
 425        ret = i2c_transfer(ts->client->adapter, msg, 2);
 426        if (ret < 0) {
 427                pr_err("i2c_transfer failed\n");
 428                goto err_detect_failed;
 429        }
 430        pr_info("synaptics_ts_probe: 0xe0: %x %x %x %x %x %x %x %x\n",
 431               buf1[0], buf1[1], buf1[2], buf1[3],
 432               buf1[4], buf1[5], buf1[6], buf1[7]);
 433
 434        ret = i2c_set(ts, 0xff, 0x10, "page select = 0x10");
 435        if (ret < 0)
 436                goto err_detect_failed;
 437
 438        ret = i2c_smbus_read_word_data(ts->client, 0x04);
 439        if (ret < 0) {
 440                pr_err("i2c_smbus_read_word_data failed\n");
 441                goto err_detect_failed;
 442        }
 443        ts->max[0] = max_x = (ret >> 8 & 0xff) | ((ret & 0x1f) << 8);
 444        ret = i2c_smbus_read_word_data(ts->client, 0x06);
 445        if (ret < 0) {
 446                pr_err("i2c_smbus_read_word_data failed\n");
 447                goto err_detect_failed;
 448        }
 449        ts->max[1] = max_y = (ret >> 8 & 0xff) | ((ret & 0x1f) << 8);
 450        if (ts->flags & SYNAPTICS_SWAP_XY)
 451                swap(max_x, max_y);
 452
 453        /* will also switch back to page 0x04 */
 454        ret = synaptics_init_panel(ts);
 455        if (ret < 0) {
 456                pr_err("synaptics_init_panel failed\n");
 457                goto err_detect_failed;
 458        }
 459
 460        ts->input_dev = input_allocate_device();
 461        if (ts->input_dev == NULL) {
 462                ret = -ENOMEM;
 463                pr_err("synaptics: Failed to allocate input device\n");
 464                goto err_input_dev_alloc_failed;
 465        }
 466        ts->input_dev->name = "synaptics-rmi-touchscreen";
 467        ts->input_dev->phys = "msm/input0";
 468        ts->input_dev->id.bustype = BUS_I2C;
 469
 470        __set_bit(EV_SYN, ts->input_dev->evbit);
 471        __set_bit(EV_KEY, ts->input_dev->evbit);
 472        __set_bit(BTN_TOUCH, ts->input_dev->keybit);
 473        __set_bit(EV_ABS, ts->input_dev->evbit);
 474
 475        compute_areas(ts, pdata, max_x, max_y);
 476
 477
 478        ret = input_register_device(ts->input_dev);
 479        if (ret) {
 480                pr_err("synaptics: Unable to register %s input device\n",
 481                       ts->input_dev->name);
 482                goto err_input_register_device_failed;
 483        }
 484        if (client->irq) {
 485                ret = request_threaded_irq(client->irq, NULL,
 486                                        synaptics_ts_irq_handler,
 487                                        IRQF_TRIGGER_LOW|IRQF_ONESHOT,
 488                                        client->name, ts);
 489                if (ret == 0) {
 490                        ret = i2c_set(ts, 0xf1, 0x01, "enable abs int");
 491                        if (ret)
 492                                free_irq(client->irq, ts);
 493                }
 494                if (ret == 0)
 495                        ts->use_irq = 1;
 496                else
 497                        dev_err(&client->dev, "request_irq failed\n");
 498        }
 499        if (!ts->use_irq) {
 500                hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 501                ts->timer.function = synaptics_ts_timer_func;
 502                hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
 503        }
 504#ifdef CONFIG_HAS_EARLYSUSPEND
 505        ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
 506        ts->early_suspend.suspend = synaptics_ts_early_suspend;
 507        ts->early_suspend.resume = synaptics_ts_late_resume;
 508        register_early_suspend(&ts->early_suspend);
 509#endif
 510
 511        pr_info("synaptics: Start touchscreen %s in %s mode\n",
 512                ts->input_dev->name, ts->use_irq ? "interrupt" : "polling");
 513
 514        return 0;
 515
 516err_input_register_device_failed:
 517        input_free_device(ts->input_dev);
 518
 519err_input_dev_alloc_failed:
 520err_detect_failed:
 521err_power_failed:
 522        kfree(ts);
 523err_alloc_data_failed:
 524err_check_functionality_failed:
 525        return ret;
 526}
 527
 528static int synaptics_ts_remove(struct i2c_client *client)
 529{
 530        struct synaptics_ts_data *ts = i2c_get_clientdata(client);
 531#ifdef CONFIG_HAS_EARLYSUSPEND
 532        unregister_early_suspend(&ts->early_suspend);
 533#endif
 534        if (ts->use_irq)
 535                free_irq(client->irq, ts);
 536        else
 537                hrtimer_cancel(&ts->timer);
 538        input_unregister_device(ts->input_dev);
 539        kfree(ts);
 540        return 0;
 541}
 542
 543#ifdef CONFIG_PM
 544static int synaptics_ts_suspend(struct i2c_client *client, pm_message_t mesg)
 545{
 546        int ret;
 547        struct synaptics_ts_data *ts = i2c_get_clientdata(client);
 548
 549        if (ts->use_irq)
 550                disable_irq(client->irq);
 551        else
 552                hrtimer_cancel(&ts->timer);
 553        ret = cancel_work_sync(&ts->work);
 554        if (ret && ts->use_irq) /* if work was pending disable-count is now 2 */
 555                enable_irq(client->irq);
 556        i2c_set(ts, 0xf1, 0, "disable interrupt");
 557        i2c_set(ts, 0xf0, 0x86, "deep sleep");
 558
 559        if (ts->power) {
 560                ret = ts->power(0);
 561                if (ret < 0)
 562                        pr_err("synaptics_ts_suspend power off failed\n");
 563        }
 564        return 0;
 565}
 566
 567static int synaptics_ts_resume(struct i2c_client *client)
 568{
 569        int ret;
 570        struct synaptics_ts_data *ts = i2c_get_clientdata(client);
 571
 572        if (ts->power) {
 573                ret = ts->power(1);
 574                if (ret < 0)
 575                        pr_err("synaptics_ts_resume power on failed\n");
 576        }
 577
 578        synaptics_init_panel(ts);
 579
 580        if (ts->use_irq) {
 581                enable_irq(client->irq);
 582                i2c_set(ts, 0xf1, 0x01, "enable abs int");
 583        } else
 584                hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
 585
 586        return 0;
 587}
 588
 589#ifdef CONFIG_HAS_EARLYSUSPEND
 590static void synaptics_ts_early_suspend(struct early_suspend *h)
 591{
 592        struct synaptics_ts_data *ts;
 593        ts = container_of(h, struct synaptics_ts_data, early_suspend);
 594        synaptics_ts_suspend(ts->client, PMSG_SUSPEND);
 595}
 596
 597static void synaptics_ts_late_resume(struct early_suspend *h)
 598{
 599        struct synaptics_ts_data *ts;
 600        ts = container_of(h, struct synaptics_ts_data, early_suspend);
 601        synaptics_ts_resume(ts->client);
 602}
 603#endif
 604#else
 605#define synaptics_ts_suspend NULL
 606#define synaptics_ts_resume NULL
 607#endif
 608
 609
 610
 611static const struct i2c_device_id synaptics_ts_id[] = {
 612        { SYNAPTICS_I2C_RMI_NAME, 0 },
 613        { }
 614};
 615
 616static struct i2c_driver synaptics_ts_driver = {
 617        .probe          = synaptics_ts_probe,
 618        .remove         = synaptics_ts_remove,
 619#ifndef CONFIG_HAS_EARLYSUSPEND
 620        .suspend        = synaptics_ts_suspend,
 621        .resume         = synaptics_ts_resume,
 622#endif
 623        .id_table       = synaptics_ts_id,
 624        .driver = {
 625                .name   = SYNAPTICS_I2C_RMI_NAME,
 626        },
 627};
 628
 629static int __devinit synaptics_ts_init(void)
 630{
 631        synaptics_wq = create_singlethread_workqueue("synaptics_wq");
 632        if (!synaptics_wq)
 633                return -ENOMEM;
 634        return i2c_add_driver(&synaptics_ts_driver);
 635}
 636
 637static void __exit synaptics_ts_exit(void)
 638{
 639        i2c_del_driver(&synaptics_ts_driver);
 640        if (synaptics_wq)
 641                destroy_workqueue(synaptics_wq);
 642}
 643
 644module_init(synaptics_ts_init);
 645module_exit(synaptics_ts_exit);
 646
 647MODULE_DESCRIPTION("Synaptics Touchscreen Driver");
 648MODULE_LICENSE("GPL");
 649MODULE_AUTHOR("Arve Hjønnevåg <arve@android.com>");
 650
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.