1eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* 2eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * Synaptics touchpad with I2C interface 3eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * 4eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * Copyright (C) 2009 Compulab, Ltd. 5eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * Mike Rapoport <mike@compulab.co.il> 6eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * Igor Grinberg <grinberg@compulab.co.il> 7eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * 8eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * This file is subject to the terms and conditions of the GNU General Public 9eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * License. See the file COPYING in the main directory of this archive for 10eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * more details. 11eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport */ 12eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 13eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#include <linux/module.h> 14eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#include <linux/i2c.h> 15eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#include <linux/irq.h> 16eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#include <linux/interrupt.h> 17eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#include <linux/input.h> 18eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#include <linux/delay.h> 19eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#include <linux/workqueue.h> 205a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 2187b2c7df329e547c1905e0b7e13bfce09cfa5cfeMark Brown#include <linux/pm.h> 22eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 23eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define DRIVER_NAME "synaptics_i2c" 24eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* maximum product id is 15 characters */ 25eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define PRODUCT_ID_LENGTH 15 26eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define REGISTER_LENGTH 8 27eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 28eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* 29eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * after soft reset, we should wait for 1 ms 30eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * before the device becomes operational 31eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport */ 32eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define SOFT_RESET_DELAY_MS 3 33eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* and after hard reset, we should wait for max 500ms */ 34eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define HARD_RESET_DELAY_MS 500 35eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 36eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Registers by SMBus address */ 37eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define PAGE_SEL_REG 0xff 38eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define DEVICE_STATUS_REG 0x09 39eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 40eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Registers by RMI address */ 41eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define DEV_CONTROL_REG 0x0000 42eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define INTERRUPT_EN_REG 0x0001 43eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define ERR_STAT_REG 0x0002 44eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define INT_REQ_STAT_REG 0x0003 45eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define DEV_COMMAND_REG 0x0004 46eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 47eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define RMI_PROT_VER_REG 0x0200 48eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define MANUFACT_ID_REG 0x0201 49eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define PHYS_INT_VER_REG 0x0202 50eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define PROD_PROPERTY_REG 0x0203 51eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define INFO_QUERY_REG0 0x0204 52eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define INFO_QUERY_REG1 (INFO_QUERY_REG0 + 1) 53eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define INFO_QUERY_REG2 (INFO_QUERY_REG0 + 2) 54eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define INFO_QUERY_REG3 (INFO_QUERY_REG0 + 3) 55eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 56eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define PRODUCT_ID_REG0 0x0210 57eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define PRODUCT_ID_REG1 (PRODUCT_ID_REG0 + 1) 58eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define PRODUCT_ID_REG2 (PRODUCT_ID_REG0 + 2) 59eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define PRODUCT_ID_REG3 (PRODUCT_ID_REG0 + 3) 60eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define PRODUCT_ID_REG4 (PRODUCT_ID_REG0 + 4) 61eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define PRODUCT_ID_REG5 (PRODUCT_ID_REG0 + 5) 62eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define PRODUCT_ID_REG6 (PRODUCT_ID_REG0 + 6) 63eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define PRODUCT_ID_REG7 (PRODUCT_ID_REG0 + 7) 64eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define PRODUCT_ID_REG8 (PRODUCT_ID_REG0 + 8) 65eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define PRODUCT_ID_REG9 (PRODUCT_ID_REG0 + 9) 66eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define PRODUCT_ID_REG10 (PRODUCT_ID_REG0 + 10) 67eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define PRODUCT_ID_REG11 (PRODUCT_ID_REG0 + 11) 68eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define PRODUCT_ID_REG12 (PRODUCT_ID_REG0 + 12) 69eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define PRODUCT_ID_REG13 (PRODUCT_ID_REG0 + 13) 70eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define PRODUCT_ID_REG14 (PRODUCT_ID_REG0 + 14) 71eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define PRODUCT_ID_REG15 (PRODUCT_ID_REG0 + 15) 72eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 73eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define DATA_REG0 0x0400 74eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define ABS_PRESSURE_REG 0x0401 75eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define ABS_MSB_X_REG 0x0402 76eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define ABS_LSB_X_REG (ABS_MSB_X_REG + 1) 77eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define ABS_MSB_Y_REG 0x0404 78eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define ABS_LSB_Y_REG (ABS_MSB_Y_REG + 1) 79eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define REL_X_REG 0x0406 80eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define REL_Y_REG 0x0407 81eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 82eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define DEV_QUERY_REG0 0x1000 83eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define DEV_QUERY_REG1 (DEV_QUERY_REG0 + 1) 84eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define DEV_QUERY_REG2 (DEV_QUERY_REG0 + 2) 85eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define DEV_QUERY_REG3 (DEV_QUERY_REG0 + 3) 86eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define DEV_QUERY_REG4 (DEV_QUERY_REG0 + 4) 87eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define DEV_QUERY_REG5 (DEV_QUERY_REG0 + 5) 88eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define DEV_QUERY_REG6 (DEV_QUERY_REG0 + 6) 89eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define DEV_QUERY_REG7 (DEV_QUERY_REG0 + 7) 90eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define DEV_QUERY_REG8 (DEV_QUERY_REG0 + 8) 91eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 92eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define GENERAL_2D_CONTROL_REG 0x1041 93eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define SENSOR_SENSITIVITY_REG 0x1044 94eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define SENS_MAX_POS_MSB_REG 0x1046 95eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define SENS_MAX_POS_LSB_REG (SENS_MAX_POS_UPPER_REG + 1) 96eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 97eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Register bits */ 98eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Device Control Register Bits */ 99eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define REPORT_RATE_1ST_BIT 6 100eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 101eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Interrupt Enable Register Bits (INTERRUPT_EN_REG) */ 102eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define F10_ABS_INT_ENA 0 103eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define F10_REL_INT_ENA 1 104eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define F20_INT_ENA 2 105eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 106eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Interrupt Request Register Bits (INT_REQ_STAT_REG | DEVICE_STATUS_REG) */ 107eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define F10_ABS_INT_REQ 0 108eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define F10_REL_INT_REQ 1 109eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define F20_INT_REQ 2 110eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Device Status Register Bits (DEVICE_STATUS_REG) */ 111eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define STAT_CONFIGURED 6 112eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define STAT_ERROR 7 113eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 114eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Device Command Register Bits (DEV_COMMAND_REG) */ 115eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define RESET_COMMAND 0x01 116eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define REZERO_COMMAND 0x02 117eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 118eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Data Register 0 Bits (DATA_REG0) */ 119eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define GESTURE 3 120eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 121eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Device Query Registers Bits */ 122eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* DEV_QUERY_REG3 */ 123eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define HAS_PALM_DETECT 1 124eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define HAS_MULTI_FING 2 125eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define HAS_SCROLLER 4 126eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define HAS_2D_SCROLL 5 127eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 128eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* General 2D Control Register Bits (GENERAL_2D_CONTROL_REG) */ 129eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define NO_DECELERATION 1 130eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define REDUCE_REPORTING 3 131eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define NO_FILTER 5 132eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 133eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Function Masks */ 134eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Device Control Register Masks (DEV_CONTROL_REG) */ 135eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define REPORT_RATE_MSK 0xc0 136eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define SLEEP_MODE_MSK 0x07 137eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 138eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Device Sleep Modes */ 139eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define FULL_AWAKE 0x0 140eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define NORMAL_OP 0x1 141eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define LOW_PWR_OP 0x2 142eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define VERY_LOW_PWR_OP 0x3 143eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define SENS_SLEEP 0x4 144eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define SLEEP_MOD 0x5 145eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define DEEP_SLEEP 0x6 146eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define HIBERNATE 0x7 147eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 148eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Interrupt Register Mask */ 149eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* (INT_REQ_STAT_REG | DEVICE_STATUS_REG | INTERRUPT_EN_REG) */ 150eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define INT_ENA_REQ_MSK 0x07 151eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define INT_ENA_ABS_MSK 0x01 152eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define INT_ENA_REL_MSK 0x02 153eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define INT_ENA_F20_MSK 0x04 154eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 155eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Device Status Register Masks (DEVICE_STATUS_REG) */ 156eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define CONFIGURED_MSK 0x40 157eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define ERROR_MSK 0x80 158eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 159eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Data Register 0 Masks */ 160eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define FINGER_WIDTH_MSK 0xf0 161eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define GESTURE_MSK 0x08 162eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define SENSOR_STATUS_MSK 0x07 163eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 164eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* 165eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * MSB Position Register Masks 166eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * ABS_MSB_X_REG | ABS_MSB_Y_REG | SENS_MAX_POS_MSB_REG | 167eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * DEV_QUERY_REG3 | DEV_QUERY_REG5 168eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport */ 169eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define MSB_POSITION_MSK 0x1f 170eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 171eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Device Query Registers Masks */ 172eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 173eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* DEV_QUERY_REG2 */ 174eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define NUM_EXTRA_POS_MSK 0x07 175eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 176eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* When in IRQ mode read the device every THREAD_IRQ_SLEEP_SECS */ 177eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define THREAD_IRQ_SLEEP_SECS 2 178eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define THREAD_IRQ_SLEEP_MSECS (THREAD_IRQ_SLEEP_SECS * MSEC_PER_SEC) 179eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 180eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* 181eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * When in Polling mode and no data received for NO_DATA_THRES msecs 182eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * reduce the polling rate to NO_DATA_SLEEP_MSECS 183eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport */ 184eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define NO_DATA_THRES (MSEC_PER_SEC) 185eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#define NO_DATA_SLEEP_MSECS (MSEC_PER_SEC / 4) 186eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 187eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Control touchpad's No Deceleration option */ 18890ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool no_decel = 1; 189eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportmodule_param(no_decel, bool, 0644); 190eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike RapoportMODULE_PARM_DESC(no_decel, "No Deceleration. Default = 1 (on)"); 191eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 192eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Control touchpad's Reduced Reporting option */ 19390ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool reduce_report; 194eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportmodule_param(reduce_report, bool, 0644); 195eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike RapoportMODULE_PARM_DESC(reduce_report, "Reduced Reporting. Default = 0 (off)"); 196eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 197eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Control touchpad's No Filter option */ 19890ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool no_filter; 199eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportmodule_param(no_filter, bool, 0644); 200eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike RapoportMODULE_PARM_DESC(no_filter, "No Filter. Default = 0 (off)"); 201eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 202eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* 203eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * touchpad Attention line is Active Low and Open Drain, 204eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * therefore should be connected to pulled up line 205eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * and the irq configuration should be set to Falling Edge Trigger 206eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport */ 207eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Control IRQ / Polling option */ 20830b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhovstatic bool polling_req; 209eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportmodule_param(polling_req, bool, 0444); 210eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike RapoportMODULE_PARM_DESC(polling_req, "Request Polling. Default = 0 (use irq)"); 211eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 212eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Control Polling Rate */ 213eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportstatic int scan_rate = 80; 214eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportmodule_param(scan_rate, int, 0644); 215eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike RapoportMODULE_PARM_DESC(scan_rate, "Polling rate in times/sec. Default = 80"); 216eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 217eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* The main device structure */ 218eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportstruct synaptics_i2c { 219eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport struct i2c_client *client; 220eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport struct input_dev *input; 221eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport struct delayed_work dwork; 22230b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov spinlock_t lock; 223eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport int no_data_count; 224eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport int no_decel_param; 225eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport int reduce_report_param; 226eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport int no_filter_param; 227eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport int scan_rate_param; 228eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport int scan_ms; 229eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport}; 230eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 231eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportstatic inline void set_scan_rate(struct synaptics_i2c *touch, int scan_rate) 232eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport{ 233eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport touch->scan_ms = MSEC_PER_SEC / scan_rate; 234eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport touch->scan_rate_param = scan_rate; 235eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport} 236eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 237eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* 238eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * Driver's initial design makes no race condition possible on i2c bus, 239eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * so there is no need in any locking. 240eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * Keep it in mind, while playing with the code. 241eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport */ 242eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportstatic s32 synaptics_i2c_reg_get(struct i2c_client *client, u16 reg) 243eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport{ 244eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport int ret; 245eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 246eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport ret = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8); 247eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (ret == 0) 248eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport ret = i2c_smbus_read_byte_data(client, reg & 0xff); 249eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 250eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return ret; 251eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport} 252eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 253eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportstatic s32 synaptics_i2c_reg_set(struct i2c_client *client, u16 reg, u8 val) 254eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport{ 255eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport int ret; 256eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 257eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport ret = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8); 258eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (ret == 0) 259eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport ret = i2c_smbus_write_byte_data(client, reg & 0xff, val); 260eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 261eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return ret; 262eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport} 263eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 264eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportstatic s32 synaptics_i2c_word_get(struct i2c_client *client, u16 reg) 265eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport{ 266eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport int ret; 267eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 268eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport ret = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8); 269eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (ret == 0) 270eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport ret = i2c_smbus_read_word_data(client, reg & 0xff); 271eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 272eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return ret; 273eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport} 274eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 275eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportstatic int synaptics_i2c_config(struct i2c_client *client) 276eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport{ 277eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport int ret, control; 278eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport u8 int_en; 279eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 280eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport /* set Report Rate to Device Highest (>=80) and Sleep to normal */ 281eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport ret = synaptics_i2c_reg_set(client, DEV_CONTROL_REG, 0xc1); 282eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (ret) 283eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return ret; 284eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 285eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport /* set Interrupt Disable to Func20 / Enable to Func10) */ 286eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport int_en = (polling_req) ? 0 : INT_ENA_ABS_MSK | INT_ENA_REL_MSK; 287eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport ret = synaptics_i2c_reg_set(client, INTERRUPT_EN_REG, int_en); 288eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (ret) 289eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return ret; 290eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 291eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport control = synaptics_i2c_reg_get(client, GENERAL_2D_CONTROL_REG); 292eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport /* No Deceleration */ 293eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport control |= no_decel ? 1 << NO_DECELERATION : 0; 294eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport /* Reduced Reporting */ 295eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport control |= reduce_report ? 1 << REDUCE_REPORTING : 0; 296eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport /* No Filter */ 297eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport control |= no_filter ? 1 << NO_FILTER : 0; 298eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport ret = synaptics_i2c_reg_set(client, GENERAL_2D_CONTROL_REG, control); 299eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (ret) 300eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return ret; 301eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 302eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return 0; 303eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport} 304eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 305eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportstatic int synaptics_i2c_reset_config(struct i2c_client *client) 306eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport{ 307eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport int ret; 308eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 309eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport /* Reset the Touchpad */ 310eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport ret = synaptics_i2c_reg_set(client, DEV_COMMAND_REG, RESET_COMMAND); 311eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (ret) { 312eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport dev_err(&client->dev, "Unable to reset device\n"); 313eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport } else { 314eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport msleep(SOFT_RESET_DELAY_MS); 315eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport ret = synaptics_i2c_config(client); 316eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (ret) 317eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport dev_err(&client->dev, "Unable to config device\n"); 318eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport } 319eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 320eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return ret; 321eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport} 322eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 323eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportstatic int synaptics_i2c_check_error(struct i2c_client *client) 324eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport{ 325eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport int status, ret = 0; 326eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 327eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport status = i2c_smbus_read_byte_data(client, DEVICE_STATUS_REG) & 328eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport (CONFIGURED_MSK | ERROR_MSK); 329eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 330eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (status != CONFIGURED_MSK) 331eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport ret = synaptics_i2c_reset_config(client); 332eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 333eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return ret; 334eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport} 335eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 336eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportstatic bool synaptics_i2c_get_input(struct synaptics_i2c *touch) 337eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport{ 338eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport struct input_dev *input = touch->input; 339eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport int xy_delta, gesture; 340eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport s32 data; 341eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport s8 x_delta, y_delta; 342eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 343eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport /* Deal with spontanious resets and errors */ 344eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (synaptics_i2c_check_error(touch->client)) 345eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return 0; 346eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 347eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport /* Get Gesture Bit */ 348eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport data = synaptics_i2c_reg_get(touch->client, DATA_REG0); 349eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport gesture = (data >> GESTURE) & 0x1; 350eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 351eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport /* 352eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * Get Relative axes. we have to get them in one shot, 353eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * so we get 2 bytes starting from REL_X_REG. 354eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport */ 355eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport xy_delta = synaptics_i2c_word_get(touch->client, REL_X_REG) & 0xffff; 356eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 357eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport /* Separate X from Y */ 358eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport x_delta = xy_delta & 0xff; 359eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport y_delta = (xy_delta >> REGISTER_LENGTH) & 0xff; 360eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 361eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport /* Report the button event */ 362eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport input_report_key(input, BTN_LEFT, gesture); 363eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 364eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport /* Report the deltas */ 365eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport input_report_rel(input, REL_X, x_delta); 366eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport input_report_rel(input, REL_Y, -y_delta); 367eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport input_sync(input); 368eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 369eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return xy_delta || gesture; 370eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport} 371eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 37230b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhovstatic void synaptics_i2c_reschedule_work(struct synaptics_i2c *touch, 37330b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov unsigned long delay) 374eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport{ 37530b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov unsigned long flags; 37630b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov 37730b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov spin_lock_irqsave(&touch->lock, flags); 378eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 379eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport /* 38030b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov * If work is already scheduled then subsequent schedules will not 38130b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov * change the scheduled time that's why we have to cancel it first. 382eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport */ 38330b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov __cancel_delayed_work(&touch->dwork); 38430b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov schedule_delayed_work(&touch->dwork, delay); 38530b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov 38630b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov spin_unlock_irqrestore(&touch->lock, flags); 38730b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov} 38830b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov 38930b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhovstatic irqreturn_t synaptics_i2c_irq(int irq, void *dev_id) 39030b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov{ 39130b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov struct synaptics_i2c *touch = dev_id; 39230b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov 39330b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov synaptics_i2c_reschedule_work(touch, 0); 394eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 395eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return IRQ_HANDLED; 396eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport} 397eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 398eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportstatic void synaptics_i2c_check_params(struct synaptics_i2c *touch) 399eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport{ 400eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport bool reset = false; 401eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 402eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (scan_rate != touch->scan_rate_param) 403eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport set_scan_rate(touch, scan_rate); 404eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 405eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (no_decel != touch->no_decel_param) { 406eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport touch->no_decel_param = no_decel; 407eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport reset = true; 408eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport } 409eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 410eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (no_filter != touch->no_filter_param) { 411eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport touch->no_filter_param = no_filter; 412eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport reset = true; 413eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport } 414eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 415eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (reduce_report != touch->reduce_report_param) { 416eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport touch->reduce_report_param = reduce_report; 417eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport reset = true; 418eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport } 419eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 420eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (reset) 421eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport synaptics_i2c_reset_config(touch->client); 422eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport} 423eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 424eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Control the Device polling rate / Work Handler sleep time */ 425f5ba35023697e54a24487bcd822194390a333893Dmitry Torokhovstatic unsigned long synaptics_i2c_adjust_delay(struct synaptics_i2c *touch, 426f5ba35023697e54a24487bcd822194390a333893Dmitry Torokhov bool have_data) 427eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport{ 428eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport unsigned long delay, nodata_count_thres; 429eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 430eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (polling_req) { 431eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport delay = touch->scan_ms; 432eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (have_data) { 433eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport touch->no_data_count = 0; 434eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport } else { 435eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport nodata_count_thres = NO_DATA_THRES / touch->scan_ms; 436eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (touch->no_data_count < nodata_count_thres) 437eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport touch->no_data_count++; 438eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport else 439eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport delay = NO_DATA_SLEEP_MSECS; 440eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport } 441eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return msecs_to_jiffies(delay); 442eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport } else { 443eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport delay = msecs_to_jiffies(THREAD_IRQ_SLEEP_MSECS); 444eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return round_jiffies_relative(delay); 445eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport } 446eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport} 447eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 448eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport/* Work Handler */ 449eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportstatic void synaptics_i2c_work_handler(struct work_struct *work) 450eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport{ 451eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport bool have_data; 452eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport struct synaptics_i2c *touch = 453eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport container_of(work, struct synaptics_i2c, dwork.work); 454eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport unsigned long delay; 455eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 456eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport synaptics_i2c_check_params(touch); 457eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 458eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport have_data = synaptics_i2c_get_input(touch); 459eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport delay = synaptics_i2c_adjust_delay(touch, have_data); 460eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 461eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport /* 462eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * While interrupt driven, there is no real need to poll the device. 463eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * But touchpads are very sensitive, so there could be errors 464eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * related to physical environment and the attention line isn't 46525985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * necessarily asserted. In such case we can lose the touchpad. 466eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * We poll the device once in THREAD_IRQ_SLEEP_SECS and 467eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport * if error is detected, we try to reset and reconfigure the touchpad. 468eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport */ 46930b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov synaptics_i2c_reschedule_work(touch, delay); 470eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport} 471eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 472eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportstatic int synaptics_i2c_open(struct input_dev *input) 473eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport{ 474eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport struct synaptics_i2c *touch = input_get_drvdata(input); 475eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport int ret; 476eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 477eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport ret = synaptics_i2c_reset_config(touch->client); 478eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (ret) 479eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return ret; 480eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 481eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (polling_req) 48230b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov synaptics_i2c_reschedule_work(touch, 48330b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); 484eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 485eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return 0; 486eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport} 487eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 488eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportstatic void synaptics_i2c_close(struct input_dev *input) 489eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport{ 490eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport struct synaptics_i2c *touch = input_get_drvdata(input); 491eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 492eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (!polling_req) 493eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport synaptics_i2c_reg_set(touch->client, INTERRUPT_EN_REG, 0); 494eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 495eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport cancel_delayed_work_sync(&touch->dwork); 496eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 497eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport /* Save some power */ 498eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport synaptics_i2c_reg_set(touch->client, DEV_CONTROL_REG, DEEP_SLEEP); 499eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport} 500eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 501eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportstatic void synaptics_i2c_set_input_params(struct synaptics_i2c *touch) 502eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport{ 503eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport struct input_dev *input = touch->input; 504eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 505eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport input->name = touch->client->name; 506eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport input->phys = touch->client->adapter->name; 507eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport input->id.bustype = BUS_I2C; 508eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport input->id.version = synaptics_i2c_word_get(touch->client, 509eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport INFO_QUERY_REG0); 510eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport input->dev.parent = &touch->client->dev; 511eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport input->open = synaptics_i2c_open; 512eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport input->close = synaptics_i2c_close; 513eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport input_set_drvdata(input, touch); 514eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 515eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport /* Register the device as mouse */ 516eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport __set_bit(EV_REL, input->evbit); 517eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport __set_bit(REL_X, input->relbit); 518eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport __set_bit(REL_Y, input->relbit); 519eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 520eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport /* Register device's buttons and keys */ 521eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport __set_bit(EV_KEY, input->evbit); 522eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport __set_bit(BTN_LEFT, input->keybit); 523eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport} 524eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 525f5ba35023697e54a24487bcd822194390a333893Dmitry Torokhovstatic struct synaptics_i2c *synaptics_i2c_touch_create(struct i2c_client *client) 526eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport{ 527eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport struct synaptics_i2c *touch; 528eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 529eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport touch = kzalloc(sizeof(struct synaptics_i2c), GFP_KERNEL); 530eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (!touch) 531eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return NULL; 532eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 533eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport touch->client = client; 534eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport touch->no_decel_param = no_decel; 535eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport touch->scan_rate_param = scan_rate; 536eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport set_scan_rate(touch, scan_rate); 537eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport INIT_DELAYED_WORK(&touch->dwork, synaptics_i2c_work_handler); 53830b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov spin_lock_init(&touch->lock); 539eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 540eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return touch; 541eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport} 542eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 543eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportstatic int __devinit synaptics_i2c_probe(struct i2c_client *client, 544eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport const struct i2c_device_id *dev_id) 545eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport{ 546eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport int ret; 547eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport struct synaptics_i2c *touch; 548eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 549eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport touch = synaptics_i2c_touch_create(client); 550eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (!touch) 551eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return -ENOMEM; 552eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 553eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport ret = synaptics_i2c_reset_config(client); 554eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (ret) 555eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport goto err_mem_free; 556eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 557eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (client->irq < 1) 55830b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov polling_req = true; 559eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 560eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport touch->input = input_allocate_device(); 561eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (!touch->input) { 562eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport ret = -ENOMEM; 563eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport goto err_mem_free; 564eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport } 565eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 566eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport synaptics_i2c_set_input_params(touch); 567eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 568eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (!polling_req) { 569eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport dev_dbg(&touch->client->dev, 570eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport "Requesting IRQ: %d\n", touch->client->irq); 571eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 572eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport ret = request_irq(touch->client->irq, synaptics_i2c_irq, 573ec4665c46b11f6e444911ba73dddae6044dec909Yong Zhang IRQ_TYPE_EDGE_FALLING, 574eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport DRIVER_NAME, touch); 575eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (ret) { 576eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport dev_warn(&touch->client->dev, 577eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport "IRQ request failed: %d, " 578eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport "falling back to polling\n", ret); 57930b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov polling_req = true; 580eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport synaptics_i2c_reg_set(touch->client, 581eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport INTERRUPT_EN_REG, 0); 582eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport } 583eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport } 584eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 585eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (polling_req) 586eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport dev_dbg(&touch->client->dev, 587eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport "Using polling at rate: %d times/sec\n", scan_rate); 588eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 589eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport /* Register the device in input subsystem */ 590eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport ret = input_register_device(touch->input); 591eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (ret) { 592eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport dev_err(&client->dev, 593eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport "Input device register failed: %d\n", ret); 594eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport goto err_input_free; 595eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport } 59630b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov 59730b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov i2c_set_clientdata(client, touch); 59830b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov 599eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return 0; 600eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 601eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoporterr_input_free: 602eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport input_free_device(touch->input); 603eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoporterr_mem_free: 604eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport kfree(touch); 605eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 606eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return ret; 607eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport} 608eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 609eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportstatic int __devexit synaptics_i2c_remove(struct i2c_client *client) 610eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport{ 611eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport struct synaptics_i2c *touch = i2c_get_clientdata(client); 612eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 613eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (!polling_req) 61430b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov free_irq(client->irq, touch); 615eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 616eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport input_unregister_device(touch->input); 617eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport kfree(touch); 618eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 619eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return 0; 620eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport} 621eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 62226e56eb2bfccdd6bcec0c298d40e12e3daea0188Dmitry Torokhov#ifdef CONFIG_PM_SLEEP 62387b2c7df329e547c1905e0b7e13bfce09cfa5cfeMark Brownstatic int synaptics_i2c_suspend(struct device *dev) 624eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport{ 62587b2c7df329e547c1905e0b7e13bfce09cfa5cfeMark Brown struct i2c_client *client = to_i2c_client(dev); 626eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport struct synaptics_i2c *touch = i2c_get_clientdata(client); 627eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 628eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport cancel_delayed_work_sync(&touch->dwork); 629eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 630eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport /* Save some power */ 631eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport synaptics_i2c_reg_set(touch->client, DEV_CONTROL_REG, DEEP_SLEEP); 632eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 633eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return 0; 634eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport} 635eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 63687b2c7df329e547c1905e0b7e13bfce09cfa5cfeMark Brownstatic int synaptics_i2c_resume(struct device *dev) 637eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport{ 638eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport int ret; 63987b2c7df329e547c1905e0b7e13bfce09cfa5cfeMark Brown struct i2c_client *client = to_i2c_client(dev); 640eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport struct synaptics_i2c *touch = i2c_get_clientdata(client); 641eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 642eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport ret = synaptics_i2c_reset_config(client); 643eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport if (ret) 644eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return ret; 645eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 64630b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov synaptics_i2c_reschedule_work(touch, 64730b37131aa63f4f73ebc48a026666448e5907255Dmitry Torokhov msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); 648eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 649eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport return 0; 650eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport} 651eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport#endif 652eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 65387b2c7df329e547c1905e0b7e13bfce09cfa5cfeMark Brownstatic SIMPLE_DEV_PM_OPS(synaptics_i2c_pm, synaptics_i2c_suspend, 65487b2c7df329e547c1905e0b7e13bfce09cfa5cfeMark Brown synaptics_i2c_resume); 65587b2c7df329e547c1905e0b7e13bfce09cfa5cfeMark Brown 656eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportstatic const struct i2c_device_id synaptics_i2c_id_table[] = { 657eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport { "synaptics_i2c", 0 }, 658eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport { }, 659eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport}; 660eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike RapoportMODULE_DEVICE_TABLE(i2c, synaptics_i2c_id_table); 661eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 662eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoportstatic struct i2c_driver synaptics_i2c_driver = { 663eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport .driver = { 664eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport .name = DRIVER_NAME, 665eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport .owner = THIS_MODULE, 66687b2c7df329e547c1905e0b7e13bfce09cfa5cfeMark Brown .pm = &synaptics_i2c_pm, 667eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport }, 668eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 669eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport .probe = synaptics_i2c_probe, 670eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport .remove = __devexit_p(synaptics_i2c_remove), 671eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 672eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport .id_table = synaptics_i2c_id_table, 673eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport}; 674eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 6751b92c1cf6b638e7cbe9fdaac3f6efb8874f5cc02Axel Linmodule_i2c_driver(synaptics_i2c_driver); 676eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 677eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike RapoportMODULE_DESCRIPTION("Synaptics I2C touchpad driver"); 678eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike RapoportMODULE_AUTHOR("Mike Rapoport, Igor Grinberg, Compulab"); 679eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike RapoportMODULE_LICENSE("GPL"); 680eef3e4cab72eaf5345e3c73b2975c194a714f6cdMike Rapoport 681