From 50f1e17cd7605b412289199d719c65169fcdd96f Mon Sep 17 00:00:00 2001 From: Hong Liu Date: Tue, 7 Feb 2012 18:02:34 +0800 Subject: [PATCH] atmel_mxt_ts: revert changes to the upstream atmel_mxt_ts driver BZ: 20808 Revert the changes to prepare for applying the OTC patches to this driver. Change-Id: Ia3b8db53861069e12d7e3237ae62d11fd12341d0 Signed-off-by: Hong Liu Reviewed-on: http://android.intel.com:8080/34434 Reviewed-by: Continente, Christophe Reviewed-by: Chotard, Celine Tested-by: Chotard, Celine Reviewed-by: buildbot Tested-by: buildbot --- arch/x86/platform/intel-mid/board-redridge.c | 42 - drivers/input/touchscreen/atmel_mxt_ts.c | 2856 +++++++++----------------- include/linux/atmel_mxt_ts.h | 377 ---- 3 files changed, 991 insertions(+), 2284 deletions(-) delete mode 100644 include/linux/atmel_mxt_ts.h diff --git a/arch/x86/platform/intel-mid/board-redridge.c b/arch/x86/platform/intel-mid/board-redridge.c index d93b663..61319bb 100644 --- a/arch/x86/platform/intel-mid/board-redridge.c +++ b/arch/x86/platform/intel-mid/board-redridge.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #include @@ -1098,20 +1097,6 @@ void *wl12xx_platform_data_init(void *info) } #endif -void *mxt_platform_data_init(void *info) -{ - static struct mxt_platform_data mxt_pdata; - - mxt_pdata.numtouch = 10; - mxt_pdata.max_x = 1023; - mxt_pdata.max_y = 975; - mxt_pdata.orientation = MXT_MSGB_T9_ORIENT_HORZ_FLIP; - mxt_pdata.reset = 129; - mxt_pdata.irq = 62; - - return &mxt_pdata; -} - #define AUDIENCE_WAKEUP_GPIO "audience-wakeup" #define AUDIENCE_RESET_GPIO "audience-reset" static int audience_request_resources(struct i2c_client *client) @@ -1592,7 +1577,6 @@ struct devs_id __initconst device_ids[] = { &intel_ignore_i2c_device_register}, {"mt9m114", SFI_DEV_TYPE_I2C, 0, &mt9m114_platform_data_init, &intel_ignore_i2c_device_register}, - {"mxt1386", SFI_DEV_TYPE_I2C, 0, &mxt_platform_data_init, NULL}, {"audience_es305", SFI_DEV_TYPE_I2C, 0, &audience_platform_data_init, NULL}, {"accel", SFI_DEV_TYPE_I2C, 0, &lis3dh_pdata_init, NULL}, @@ -1994,29 +1978,3 @@ static int __init blackbay_i2c_init(void) return 0; } device_initcall(blackbay_i2c_init); -/* - * mxt1386 initialization routines for Redridge board - * (Should be removed once SFI tables are updated) - */ -static struct mxt_platform_data mxt1386_pdata = { - .numtouch = 10, - .max_x = 1023, - .max_y = 975, - .orientation = MXT_MSGB_T9_ORIENT_HORZ_FLIP, - .reset = 129, - .irq = 62, -}; -static struct i2c_board_info dv10_i2c_bus0_devs[] = { - { - .type = "mxt1386", - .addr = 0x4C, - .platform_data = &mxt1386_pdata, - }, -}; -static int __init redridge_i2c_init(void) -{ - i2c_register_board_info(0, dv10_i2c_bus0_devs, - ARRAY_SIZE(dv10_i2c_bus0_devs)); - return 0; -} -device_initcall(redridge_i2c_init); diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 0b5b646d..1e61387 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -1,2117 +1,1243 @@ /* - * Atmel maXTouch Touchscreen Controller Driver + * Atmel maXTouch Touchscreen driver * + * Copyright (C) 2010 Samsung Electronics Co.Ltd + * Author: Joonyoung Shim * - * Copyright (C) 2010 Atmel Corporation - * Copyright (C) 2010 Ulf Samuelsson (ulf@atmel.com) - * Copyright (C) 2009 Raphael Derosso Pereira - * Contains changes by Wind River Systems, 2010-09-29 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. * */ +#include +#include +#include +#include #include +#include +#include #include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -/* 1-->WINTEK 0-->SINTEK */ -#define TOUCH_PANEL_IS_WINTEK 0 -#define MAGIC_PRODUCT_T38_BYTE7_WINTEK 0x02 -#define MAGIC_PRODUCT_T38_BYTE7_SINTEK 0x03 -#if TOUCH_PANEL_IS_WINTEK -#define MAGIC_PRODUCT_T38_BYTE7 MAGIC_PRODUCT_T38_BYTE7_WINTEK -#else /* SINTEK */ -#define MAGIC_PRODUCT_T38_BYTE7 MAGIC_PRODUCT_T38_BYTE7_SINTEK -#endif -/* Routines for memory access within a 16 bit address space */ -static void mxt_calibrate(struct i2c_client *client); -static int mxt_read_block(struct i2c_client *client, u16 addr, u16 length, - u8 *value); -static int mxt_write_byte(struct i2c_client *client, u16 addr, u8 value); -static int mxt_write_block(struct i2c_client *client, u16 addr, u16 length, - u8 *value); -#ifdef CONFIG_HAS_EARLYSUSPEND -void mxt_early_suspend(struct early_suspend *h); -void mxt_late_resume(struct early_suspend *h); -#endif - -#ifdef CONFIG_DEBUG_FS -static int intel_mid_add_debugfs(void); -static unsigned char reg_add = 0; -static unsigned char reg_add_offset = 0; -#endif - -#define DRIVER_VERSION "0.9a" -#define MULTI_TOUCH_ENABLED 1 -#define MXT_RESET_DELAY 65 /* ms */ -static int debug = DEBUG_INFO; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Activate debugging output"); - -static int stored_size[MXT_MAX_NUM_TOUCHES]; -static int stored_x[MXT_MAX_NUM_TOUCHES]; -static int stored_y[MXT_MAX_NUM_TOUCHES]; -static int iForceUpdateConfigValue = 0; -static struct mxt_data *mxt_es; -/* For backup NVM */ -u8 mxt_debug = 1; -u16 T6_addr; -u16 T38_addr; -u8 v20_T38[] = { 11, 10, 26, 1, 0, 0, 0, MAGIC_PRODUCT_T38_BYTE7 }; -u8 arg1 = 0; -u8 arg2 = 0; -u8 mxt_cmd = 0; -u16 low_boundary = 0; -u16 high_boundary = 0; -u8 slave_addr = MXT1386_I2C_ADDR1; - -/* Device Info descriptor */ -/* Parsed from maXTouch "Id information" inside device */ -struct mxt_device_info { - u8 family_id; - u8 variant_id; - u8 major; - u8 minor; - u8 build; - u8 num_objs; - u8 x_size; - u8 y_size; - char family_name[16]; /* Family name */ - char variant_name[16]; /* Variant name */ - u16 num_nodes; /* Number of sensor nodes */ +/* Version */ +#define MXT_VER_20 20 +#define MXT_VER_21 21 +#define MXT_VER_22 22 + +/* Slave addresses */ +#define MXT_APP_LOW 0x4a +#define MXT_APP_HIGH 0x4b +#define MXT_BOOT_LOW 0x24 +#define MXT_BOOT_HIGH 0x25 + +/* Firmware */ +#define MXT_FW_NAME "maxtouch.fw" + +/* Registers */ +#define MXT_FAMILY_ID 0x00 +#define MXT_VARIANT_ID 0x01 +#define MXT_VERSION 0x02 +#define MXT_BUILD 0x03 +#define MXT_MATRIX_X_SIZE 0x04 +#define MXT_MATRIX_Y_SIZE 0x05 +#define MXT_OBJECT_NUM 0x06 +#define MXT_OBJECT_START 0x07 + +#define MXT_OBJECT_SIZE 6 + +/* Object types */ +#define MXT_DEBUG_DIAGNOSTIC 37 +#define MXT_GEN_MESSAGE 5 +#define MXT_GEN_COMMAND 6 +#define MXT_GEN_POWER 7 +#define MXT_GEN_ACQUIRE 8 +#define MXT_TOUCH_MULTI 9 +#define MXT_TOUCH_KEYARRAY 15 +#define MXT_TOUCH_PROXIMITY 23 +#define MXT_PROCI_GRIPFACE 20 +#define MXT_PROCG_NOISE 22 +#define MXT_PROCI_ONETOUCH 24 +#define MXT_PROCI_TWOTOUCH 27 +#define MXT_PROCI_GRIP 40 +#define MXT_PROCI_PALM 41 +#define MXT_SPT_COMMSCONFIG 18 +#define MXT_SPT_GPIOPWM 19 +#define MXT_SPT_SELFTEST 25 +#define MXT_SPT_CTECONFIG 28 +#define MXT_SPT_USERDATA 38 +#define MXT_SPT_DIGITIZER 43 +#define MXT_SPT_MESSAGECOUNT 44 + +/* MXT_GEN_COMMAND field */ +#define MXT_COMMAND_RESET 0 +#define MXT_COMMAND_BACKUPNV 1 +#define MXT_COMMAND_CALIBRATE 2 +#define MXT_COMMAND_REPORTALL 3 +#define MXT_COMMAND_DIAGNOSTIC 5 + +/* MXT_GEN_POWER field */ +#define MXT_POWER_IDLEACQINT 0 +#define MXT_POWER_ACTVACQINT 1 +#define MXT_POWER_ACTV2IDLETO 2 + +/* MXT_GEN_ACQUIRE field */ +#define MXT_ACQUIRE_CHRGTIME 0 +#define MXT_ACQUIRE_TCHDRIFT 2 +#define MXT_ACQUIRE_DRIFTST 3 +#define MXT_ACQUIRE_TCHAUTOCAL 4 +#define MXT_ACQUIRE_SYNC 5 +#define MXT_ACQUIRE_ATCHCALST 6 +#define MXT_ACQUIRE_ATCHCALSTHR 7 + +/* MXT_TOUCH_MULTI field */ +#define MXT_TOUCH_CTRL 0 +#define MXT_TOUCH_XORIGIN 1 +#define MXT_TOUCH_YORIGIN 2 +#define MXT_TOUCH_XSIZE 3 +#define MXT_TOUCH_YSIZE 4 +#define MXT_TOUCH_BLEN 6 +#define MXT_TOUCH_TCHTHR 7 +#define MXT_TOUCH_TCHDI 8 +#define MXT_TOUCH_ORIENT 9 +#define MXT_TOUCH_MOVHYSTI 11 +#define MXT_TOUCH_MOVHYSTN 12 +#define MXT_TOUCH_NUMTOUCH 14 +#define MXT_TOUCH_MRGHYST 15 +#define MXT_TOUCH_MRGTHR 16 +#define MXT_TOUCH_AMPHYST 17 +#define MXT_TOUCH_XRANGE_LSB 18 +#define MXT_TOUCH_XRANGE_MSB 19 +#define MXT_TOUCH_YRANGE_LSB 20 +#define MXT_TOUCH_YRANGE_MSB 21 +#define MXT_TOUCH_XLOCLIP 22 +#define MXT_TOUCH_XHICLIP 23 +#define MXT_TOUCH_YLOCLIP 24 +#define MXT_TOUCH_YHICLIP 25 +#define MXT_TOUCH_XEDGECTRL 26 +#define MXT_TOUCH_XEDGEDIST 27 +#define MXT_TOUCH_YEDGECTRL 28 +#define MXT_TOUCH_YEDGEDIST 29 +#define MXT_TOUCH_JUMPLIMIT 30 + +/* MXT_PROCI_GRIPFACE field */ +#define MXT_GRIPFACE_CTRL 0 +#define MXT_GRIPFACE_XLOGRIP 1 +#define MXT_GRIPFACE_XHIGRIP 2 +#define MXT_GRIPFACE_YLOGRIP 3 +#define MXT_GRIPFACE_YHIGRIP 4 +#define MXT_GRIPFACE_MAXTCHS 5 +#define MXT_GRIPFACE_SZTHR1 7 +#define MXT_GRIPFACE_SZTHR2 8 +#define MXT_GRIPFACE_SHPTHR1 9 +#define MXT_GRIPFACE_SHPTHR2 10 +#define MXT_GRIPFACE_SUPEXTTO 11 + +/* MXT_PROCI_NOISE field */ +#define MXT_NOISE_CTRL 0 +#define MXT_NOISE_OUTFLEN 1 +#define MXT_NOISE_GCAFUL_LSB 3 +#define MXT_NOISE_GCAFUL_MSB 4 +#define MXT_NOISE_GCAFLL_LSB 5 +#define MXT_NOISE_GCAFLL_MSB 6 +#define MXT_NOISE_ACTVGCAFVALID 7 +#define MXT_NOISE_NOISETHR 8 +#define MXT_NOISE_FREQHOPSCALE 10 +#define MXT_NOISE_FREQ0 11 +#define MXT_NOISE_FREQ1 12 +#define MXT_NOISE_FREQ2 13 +#define MXT_NOISE_FREQ3 14 +#define MXT_NOISE_FREQ4 15 +#define MXT_NOISE_IDLEGCAFVALID 16 + +/* MXT_SPT_COMMSCONFIG */ +#define MXT_COMMS_CTRL 0 +#define MXT_COMMS_CMD 1 + +/* MXT_SPT_CTECONFIG field */ +#define MXT_CTE_CTRL 0 +#define MXT_CTE_CMD 1 +#define MXT_CTE_MODE 2 +#define MXT_CTE_IDLEGCAFDEPTH 3 +#define MXT_CTE_ACTVGCAFDEPTH 4 +#define MXT_CTE_VOLTAGE 5 + +#define MXT_VOLTAGE_DEFAULT 2700000 +#define MXT_VOLTAGE_STEP 10000 + +/* Define for MXT_GEN_COMMAND */ +#define MXT_BOOT_VALUE 0xa5 +#define MXT_BACKUP_VALUE 0x55 +#define MXT_BACKUP_TIME 25 /* msec */ +#define MXT_RESET_TIME 65 /* msec */ + +#define MXT_FWRESET_TIME 175 /* msec */ + +/* Command to unlock bootloader */ +#define MXT_UNLOCK_CMD_MSB 0xaa +#define MXT_UNLOCK_CMD_LSB 0xdc + +/* Bootloader mode status */ +#define MXT_WAITING_BOOTLOAD_CMD 0xc0 /* valid 7 6 bit only */ +#define MXT_WAITING_FRAME_DATA 0x80 /* valid 7 6 bit only */ +#define MXT_FRAME_CRC_CHECK 0x02 +#define MXT_FRAME_CRC_FAIL 0x03 +#define MXT_FRAME_CRC_PASS 0x04 +#define MXT_APP_CRC_FAIL 0x40 /* valid 7 8 bit only */ +#define MXT_BOOT_STATUS_MASK 0x3f + +/* Touch status */ +#define MXT_SUPPRESS (1 << 1) +#define MXT_AMP (1 << 2) +#define MXT_VECTOR (1 << 3) +#define MXT_MOVE (1 << 4) +#define MXT_RELEASE (1 << 5) +#define MXT_PRESS (1 << 6) +#define MXT_DETECT (1 << 7) + +/* Touch orient bits */ +#define MXT_XY_SWITCH (1 << 0) +#define MXT_X_INVERT (1 << 1) +#define MXT_Y_INVERT (1 << 2) + +/* Touchscreen absolute values */ +#define MXT_MAX_AREA 0xff + +#define MXT_MAX_FINGER 10 + +struct mxt_info { + u8 family_id; + u8 variant_id; + u8 version; + u8 build; + u8 matrix_xsize; + u8 matrix_ysize; + u8 object_num; }; -/* object descriptor table, parsed from maXTouch "object table" */ struct mxt_object { - u16 chip_addr; - u8 type; - u8 size; - u8 instances; - u8 num_report_ids; + u8 type; + u16 start_address; + u8 size; + u8 instances; + u8 num_report_ids; + + /* to map object and message */ + u8 max_reportid; }; - -/* Mapping from report id to object type and instance */ -struct report_id_map { - u8 object; - u8 instance; -/* - * This is the first report ID belonging to object. It enables us to - * find out easily the touch number: each touch has different report - * ID (which are assigned to touches in increasing order). By - * subtracting the first report ID from current, we get the touch - * number. - */ - u8 first_rid; +struct mxt_message { + u8 reportid; + u8 message[7]; + u8 checksum; }; - -/* Driver datastructure */ -struct mxt_data { - struct i2c_client *client; - struct mutex dev_mutex; - struct input_dev *touch_input; - struct input_dev *key_input; - char touch_phys_name[32]; - char key_phys_name[32]; - int irq; - - u16 last_read_addr; - bool new_msgs; - - int valid_irq_counter; - int invalid_irq_counter; - int irq_counter; - int message_counter; - int read_fail_counter; - - int bytes_to_read; - - u8 xpos_format; - u8 ypos_format; - - u8 numtouch; - - struct mxt_device_info device_info; - - u32 info_block_crc; - u32 configuration_crc; - u16 report_id_count; - struct report_id_map *rid_map; - struct mxt_object *object_table; - - u16 msg_proc_addr; - u8 message_size; - - u16 max_x_val; - u16 max_y_val; - u16 orientation; - - void (*init_hw)(void); - void (*exit_hw)(void); - u8 (*valid_interrupt)(void); - u8 (*read_chg)(void); - -#ifdef CONFIG_HAS_EARLYSUSPEND - u8 T7[3]; - struct early_suspend es; - bool suspended; -#endif - /* Put only non-touch messages to buffer if this is set */ - char nontouch_msg_only; - - int prev_key; - - int mxt_intr_gpio; - int mxt_reset_gpio; - - u8 *message_buf; - int recal_flag; - u64 timestamp; - u16 finger_pressed; - u8 finger_count; - u8 first_pressed; - u8 grip_suppression; - u8 face_suppression; - - struct point_info pre_data[10]; +struct mxt_finger { + int status; + int x; + int y; + int area; }; -/* - * This struct is used for i2c transfers. - */ -struct mxt_i2c_byte_transfer { - __le16 le_addr; - u8 data; -} __attribute__ ((packed)); - -#define I2C_RETRY_COUNT 5 -#define I2C_PAYLOAD_SIZE 254 - -/* - * Check whether we have multi-touch enabled kernel; if not, report just the - * first touch (on mXT224, the maximum is 10 simultaneous touches). - * Because just the 1st one is reported, it might seem that the screen is not - * responding to touch if the first touch is removed while the screen is being - * touched by another finger, so beware. - * - * TODO: investigate if there is any standard set of input events that upper - * layers are expecting from a touchscreen? These can however be different for - * different platforms, and customers may have different opinions too about - * what should be interpreted as right-click, for example. - * - */ - -static const u8 *obj_typ_name[] = { - [0] = "Reserved", - [5] = "GEN_MESSAGEPROCESSOR_T5", - [6] = "GEN_COMMANDPROCESSOR_T6", - [7] = "GEN_POWERCONFIG_T7", - [8] = "GEN_ACQUIRECONFIG_T8", - [9] = "TOUCH_MULTITOUCHSCREEN_T9", - [15] = "TOUCH_KEYARRAY_T15", - [18] = "SPT_COMMSCONFIG_T18", - [19] = "SPT_GPIOPWM_T19", - [20] = "PROCI_GRIPFACESUPPRESSION_T20", - [22] = "PROCG_NOISESUPPRESSION_T22", - [23] = "TOUCH_PROXIMITY_T23", - [24] = "PROCI_ONETOUCHGESTUREPROCESSOR_T24", - [25] = "SPT_SELFTEST_T25", - [27] = "PROCI_TWOTOUCHGESTUREPROCESSOR_T27", - [28] = "SPT_CTECONFIG_T28", - [37] = "DEBUG_DIAGNOSTICS_T37", - [38] = "SPT_USER_DATA_T38", - [40] = "PROCI_GRIPSUPPRESSION_T40", - [41] = "PROCI_PALMSUPPRESSION_T41", - [42] = "PROCI_FACESUPPRESSION_T42", - [43] = "SPT_DIGITIZER_T43", - [44] = "SPT_MESSAGECOUNT_T44", +/* Each client has this additional data */ +struct mxt_data { + struct i2c_client *client; + struct input_dev *input_dev; + const struct mxt_platform_data *pdata; + struct mxt_object *object_table; + struct mxt_info info; + struct mxt_finger finger[MXT_MAX_FINGER]; + unsigned int irq; + unsigned int max_x; + unsigned int max_y; }; -/* - * All entries spare upto 255 - */ -#define RESERVED_T255 255u -void mxt_config_init(struct mxt_data *mxt) +static bool mxt_object_readable(unsigned int type) { - int err = 0; - dev_info(&mxt->client->dev, "In function %s", __func__); - /* Fix for current comsumption. */ - u8 v20_T7[] = { 32, 16, 50 }; - u8 v20_T8[] = { 10, 0, 15, 15, 0, 0, 5, 45, 10, 192 }; -#if TOUCH_PANEL_IS_WINTEK - u8 v20_T9[] = { 143, 0, 0, 27, 42, 0, 16, 60, 3, 3, 0, 0, 3, 14, 10, 20, - 20, 10, 31, 3, 255, 4, 0, 0, 0, 0, 0, 0, 64, 0, 15, 15, - 49, 52 }; -#else /* SINTEK */ - u8 v20_T9[] = { 143, 0, 0, 28, 42, 0, 16, 60, 3, 3, 0, 0, 3, 14, 10, 20, - 20, 10, 31, 3, 255, 4, 0, 0, 0, 0, 0, 0, 64, 0, 15, 15, - 49, 52 }; -#endif - - u8 v20_T15[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - u8 v20_T18[] = { 0, 0 }; - u8 v20_T22[] = { 5, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 15, 25, 35, 255, 255, - 0 }; - u8 v20_T24[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0 }; - u8 v20_T25[] = { 3, 0, 248, 42, 112, 23, 0, 0, 0, 0, 0, 0, 0, 0 }; - u8 v20_T27[] = { 0, 0, 0, 0, 0, 0, 0 }; - u8 v20_T28[] = { 0, 0, 0, 8, 16, 60 }; - u8 v20_T40[] = { 0, 0, 0, 0, 0 }; - u8 v20_T41[] = { 1, 0, 0, 35, 5, 20, 170 }; - u8 v20_T43[] = { 0, 0, 0, 0, 0, 0 }; - - if (slave_addr == MXT1386_I2C_ADDR2) { /* 0X4C means Wintek and 0x4D means Sintek */ - v20_T9[3] = 28; - v20_T22[8] = 20; + switch (type) { + case MXT_GEN_MESSAGE: + case MXT_GEN_COMMAND: + case MXT_GEN_POWER: + case MXT_GEN_ACQUIRE: + case MXT_TOUCH_MULTI: + case MXT_TOUCH_KEYARRAY: + case MXT_TOUCH_PROXIMITY: + case MXT_PROCI_GRIPFACE: + case MXT_PROCG_NOISE: + case MXT_PROCI_ONETOUCH: + case MXT_PROCI_TWOTOUCH: + case MXT_PROCI_GRIP: + case MXT_PROCI_PALM: + case MXT_SPT_COMMSCONFIG: + case MXT_SPT_GPIOPWM: + case MXT_SPT_SELFTEST: + case MXT_SPT_CTECONFIG: + case MXT_SPT_USERDATA: + return true; + default: + return false; } +} - u8 i = 0, max_objs = 0, j = 0; - u16 addr; - struct mxt_object *obj_index; - - dev_dbg(&mxt->client->dev, "In function %s", __func__); - max_objs = mxt->device_info.num_objs; - obj_index = mxt->object_table; - - for (i = 0; i < max_objs; i++) { - addr = obj_index->chip_addr; - for (j = 1; j < I2C_RETRY_COUNT; j++) { - err = 1; - switch (obj_index->type) { - case MXT_GEN_POWERCONFIG_T7: - err = mxt_write_block(mxt->client, addr, sizeof(v20_T7), v20_T7); - break; - case MXT_GEN_ACQUIRECONFIG_T8: - err = mxt_write_block(mxt->client, addr, sizeof(v20_T8), v20_T8); - break; - case MXT_TOUCH_MULTITOUCHSCREEN_T9: - err = mxt_write_block(mxt->client, addr, sizeof(v20_T9), v20_T9); - dev_dbg(&mxt->client->dev, "init multitouch object"); - break; - case MXT_TOUCH_KEYARRAY_T15: - err = mxt_write_block(mxt->client, addr, sizeof(v20_T15), v20_T15); - break; - case MXT_SPT_COMMSCONFIG_T18: - err = mxt_write_block(mxt->client, addr, sizeof(v20_T18), v20_T18); - break; - case MXT_PROCG_NOISESUPPRESSION_T22: - err = mxt_write_block(mxt->client, addr, sizeof(v20_T22), v20_T22); - break; - case MXT_PROCI_ONETOUCHGESTUREPROCESSOR_T24: - err = mxt_write_block(mxt->client, addr, sizeof(v20_T24), v20_T24); - break; - case MXT_SPT_SELFTEST_T25: - err = mxt_write_block(mxt->client, addr, sizeof(v20_T25), v20_T25); - break; - case MXT_PROCI_TWOTOUCHGESTUREPROCESSOR_T27: - err = mxt_write_block(mxt->client, addr, sizeof(v20_T27), v20_T27); - break; - case MXT_SPT_CTECONFIG_T28: - err = mxt_write_block(mxt->client, addr, sizeof(v20_T28), v20_T28); - break; - case MXT_USER_INFO_T38: - err = mxt_write_block(mxt->client, addr, sizeof(v20_T38), v20_T38); - break; - case MXT_PROCI_GRIPSUPPRESSION_T40: - err = mxt_write_block(mxt->client, addr, sizeof(v20_T40), v20_T40); - break; - case MXT_PROCI_PALMSUPPRESSION_T41: - err = mxt_write_block(mxt->client, addr, sizeof(v20_T41), v20_T41); - break; - case MXT_SPT_DIGITIZER_T43: - err = mxt_write_block(mxt->client, addr, sizeof(v20_T43), v20_T43); - break; - default: - break; - } - if (err > 0) - break; - } - if (j >= I2C_RETRY_COUNT) - dev_info(&mxt->client->dev, - "touch: config init abnormal,obj_index's type is %d", - obj_index->type); - - obj_index++; +static bool mxt_object_writable(unsigned int type) +{ + switch (type) { + case MXT_GEN_COMMAND: + case MXT_GEN_POWER: + case MXT_GEN_ACQUIRE: + case MXT_TOUCH_MULTI: + case MXT_TOUCH_KEYARRAY: + case MXT_TOUCH_PROXIMITY: + case MXT_PROCI_GRIPFACE: + case MXT_PROCG_NOISE: + case MXT_PROCI_ONETOUCH: + case MXT_PROCI_TWOTOUCH: + case MXT_PROCI_GRIP: + case MXT_PROCI_PALM: + case MXT_SPT_GPIOPWM: + case MXT_SPT_SELFTEST: + case MXT_SPT_CTECONFIG: + return true; + default: + return false; } - mxt_calibrate(mxt->client); - dev_dbg(&mxt->client->dev, "config init Done."); } -/* Returns object address in mXT chip, or zero if object is not found */ -static u16 get_object_address(uint8_t object_type, - uint8_t instance, - struct mxt_object *object_table, - int max_objs) +static void mxt_dump_message(struct device *dev, + struct mxt_message *message) { - uint8_t object_table_index = 0; - uint8_t address_found = 0; - uint16_t address = 0; - struct mxt_object *obj; - - while ((object_table_index < max_objs) && !address_found) { - obj = &object_table[object_table_index]; - if (obj->type == object_type) { - address_found = 1; - /* Are there enough instances defined in the FW? */ - if (obj->instances >= instance) { - address = obj->chip_addr + - (obj->size + 1) * instance; - } else { - break; - } - } - object_table_index++; - } - return address; + dev_dbg(dev, "reportid:\t0x%x\n", message->reportid); + dev_dbg(dev, "message1:\t0x%x\n", message->message[0]); + dev_dbg(dev, "message2:\t0x%x\n", message->message[1]); + dev_dbg(dev, "message3:\t0x%x\n", message->message[2]); + dev_dbg(dev, "message4:\t0x%x\n", message->message[3]); + dev_dbg(dev, "message5:\t0x%x\n", message->message[4]); + dev_dbg(dev, "message6:\t0x%x\n", message->message[5]); + dev_dbg(dev, "message7:\t0x%x\n", message->message[6]); + dev_dbg(dev, "checksum:\t0x%x\n", message->checksum); } -int BackupNVM(struct mxt_data *mxt) +static int mxt_check_bootloader(struct i2c_client *client, + unsigned int state) { - u8 buf[1] = {0x55}; - u8 T38_buf[8] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; - - /* Backup the non-volatile memory (NVM). */ - T6_addr = get_object_address(MXT_GEN_COMMANDPROCESSOR_T6, 0, - mxt->object_table, mxt->device_info.num_objs); - T38_addr = get_object_address(MXT_USER_INFO_T38, 0, - mxt->object_table, mxt->device_info.num_objs); - - pr_info("BackupNVM T6_addr+1=0x%4x, T38_addr=0x%4x.\n", T6_addr+1, T38_addr); - mxt_read_block(mxt->client, T38_addr, sizeof(T38_buf), T38_buf); - - if (iForceUpdateConfigValue == 1) { - pr_info("%s force update. ver=%d.%d.%d.%d --> %d.%d.%d.%d\n", \ - __func__, \ - T38_buf[0], T38_buf[1], T38_buf[2], T38_buf[3], \ - v20_T38[0], v20_T38[1], v20_T38[2], v20_T38[3]); - } else { - #define PRINT_T38_V20() do { \ - pr_info("%s not update. ver=%d.%d.%d.%d (%d)> %d.%d.%d.%d (%d)\n", \ - __func__, \ - T38_buf[0], T38_buf[1], T38_buf[2], T38_buf[3], T38_buf[7], \ - v20_T38[0], v20_T38[1], v20_T38[2], v20_T38[3], v20_T38[7]); \ - } while (0) - - /* Check T38 previous config version. */ - if ((T38_buf[0] != 0 && T38_buf[1] != 0) && - (T38_buf[2] != 0 && T38_buf[3] != 0) && - (T38_buf[4] == 0 && T38_buf[5] == 0) && - (T38_buf[6] == 0 && T38_buf[7] == MAGIC_PRODUCT_T38_BYTE7)) { - if (T38_buf[0] > v20_T38[0]) { - PRINT_T38_V20(); - return 0; - } else if (T38_buf[0] == v20_T38[0]) { - if (T38_buf[1] > v20_T38[1]) { - PRINT_T38_V20(); - return 0; - } else if (T38_buf[1] == v20_T38[1]) { - if (T38_buf[2] > v20_T38[2]) { - PRINT_T38_V20(); - return 0; - } else if (T38_buf[2] == v20_T38[2]) { - if (T38_buf[3] >= v20_T38[3]) { - PRINT_T38_V20(); - return 0; - } - } - } - } - } else { - if (T38_buf[7] != MAGIC_PRODUCT_T38_BYTE7) { - pr_info("%s PRODUCT_T38_BYTE7 diff, force update. ver=%d.%d.%d.%d(%d) --> %d.%d.%d.%d(%d)\n", \ - __func__, \ - T38_buf[0], T38_buf[1], T38_buf[2], T38_buf[3], T38_buf[7], \ - v20_T38[0], v20_T38[1], v20_T38[2], v20_T38[3], v20_T38[7]); - } + u8 val; - } - #undef PRINT_T38_V20 +recheck: + if (i2c_master_recv(client, &val, 1) != 1) { + dev_err(&client->dev, "%s: i2c recv failed\n", __func__); + return -EIO; } - mxt_config_init(mxt); - - if (mxt_write_block(mxt->client, T6_addr+1, sizeof(buf), buf) == 1) - pr_info("Backup the configurations to non-volatile memory.\n"); - else { - pr_err("Backup the configurations to non-volatile memory failed!!!\n"); - return -1; + switch (state) { + case MXT_WAITING_BOOTLOAD_CMD: + case MXT_WAITING_FRAME_DATA: + val &= ~MXT_BOOT_STATUS_MASK; + break; + case MXT_FRAME_CRC_PASS: + if (val == MXT_FRAME_CRC_CHECK) + goto recheck; + break; + default: + return -EINVAL; } - /*Reset the IC.*/ - if (mxt_write_block(mxt->client, T6_addr, sizeof(buf), buf) == 1) - pr_info("Software reset the IC.\n"); - else { - pr_err("Software reset the IC failed!!!\n"); - return -1; + if (val != state) { + dev_err(&client->dev, "Unvalid bootloader mode state\n"); + return -EINVAL; } - msleep(400); - pr_info("BackupNVM done. ver=%d.%d.%d.%d\n", v20_T38[0], v20_T38[1], v20_T38[2], v20_T38[3]); return 0; } -/* Calculates the 24-bit CRC sum. */ -static u32 CRC_24(u32 crc, u8 byte1, u8 byte2) +static int mxt_unlock_bootloader(struct i2c_client *client) { - static const u32 crcpoly = 0x80001B; - u32 result; - u32 data_word; - - data_word = ((((u16) byte2) << 8u) | byte1); - result = ((crc << 1u) ^ data_word); - if (result & 0x1000000) - result ^= crcpoly; - return result; -} + u8 buf[2]; -/* Calibrate rz*/ -static void mxt_calibrate(struct i2c_client *client) -{ - u16 base_addr; - struct mxt_data *mxt; + buf[0] = MXT_UNLOCK_CMD_LSB; + buf[1] = MXT_UNLOCK_CMD_MSB; - mxt = i2c_get_clientdata(client); - dev_dbg(&mxt->client->dev, "In function %s", __func__); + if (i2c_master_send(client, buf, 2) != 2) { + dev_err(&client->dev, "%s: i2c send failed\n", __func__); + return -EIO; + } - base_addr = get_object_address(MXT_GEN_COMMANDPROCESSOR_T6, - 0, mxt->object_table, - mxt->device_info.num_objs); - base_addr += MXT_ADR_T6_CALIBRATE; - mxt_write_byte(mxt->client, base_addr, 0x55); + return 0; } - -/* - * Reads a block of bytes from given address from mXT chip. If we are - * reading from message window, and previous read was from message window, - * there's no need to write the address pointer: the mXT chip will - * automatically set the address pointer back to message window start. - */ - -static int mxt_read_block(struct i2c_client *client, - u16 addr, - u16 length, - u8 *value) +static int mxt_fw_write(struct i2c_client *client, + const u8 *data, unsigned int frame_size) { - struct i2c_adapter *adapter = client->adapter; - struct i2c_msg msg[2]; - __le16 le_addr; - struct mxt_data *mxt; - int err; - - mxt = i2c_get_clientdata(client); - - if (mxt != NULL) { - if ((mxt->last_read_addr == addr) && - (addr == mxt->msg_proc_addr)) { - pm_runtime_get_sync(&client->dev); - if (i2c_master_recv(client, value, length) == length) - err = length; - else - err = -EIO; - pm_runtime_put(&client->dev); - return err; - } else { - mxt->last_read_addr = addr; - } + if (i2c_master_send(client, data, frame_size) != frame_size) { + dev_err(&client->dev, "%s: i2c send failed\n", __func__); + return -EIO; } - dev_dbg(&client->dev, "Writing address pointer & reading %d bytes" - " in on i2c transaction...\n", length); - -/* FIH { */ -/* Avoid stop delay */ -#if 0 - le_addr = cpu_to_le16(addr); - msg[0].addr = client->addr; - msg[0].flags = 0x00; - msg[0].len = 2; - msg[0].buf = (u8 *) &le_addr; - - msg[1].addr = client->addr; - msg[1].flags = I2C_M_RD; - msg[1].len = length; - msg[1].buf = (u8 *) value; - pm_runtime_get_sync(&client->dev); - if (i2c_transfer(adapter, msg, 2) == 2) - err = length; - else - err = -EIO; - pm_runtime_put(&client->dev); -#else + return 0; +} + +static int __mxt_read_reg(struct i2c_client *client, + u16 reg, u16 len, void *val) { - u8 reg[2]; - reg[0] = addr & 0xFF; - reg[1] = (addr>>8) & 0xFF; - - err = i2c_master_send(client, (u8 *)reg, 2); - if (err == 2) - err = 0; - else { - msleep(100); /* For deep sleep mode */ - err = i2c_master_send(client, (u8 *)reg, 2); - if (err == 2) - err = 0; - else - err = -EIO; + struct i2c_msg xfer[2]; + u8 buf[2]; + + buf[0] = reg & 0xff; + buf[1] = (reg >> 8) & 0xff; + + /* Write register */ + xfer[0].addr = client->addr; + xfer[0].flags = 0; + xfer[0].len = 2; + xfer[0].buf = buf; + + /* Read data */ + xfer[1].addr = client->addr; + xfer[1].flags = I2C_M_RD; + xfer[1].len = len; + xfer[1].buf = val; + + if (i2c_transfer(client->adapter, xfer, 2) != 2) { + dev_err(&client->dev, "%s: i2c transfer failed\n", __func__); + return -EIO; } - if (err < 0) - return err; - - err = i2c_master_recv(client, (u8 *)value, length); - if (err == length) - err = length; - else - err = -EIO; -} -#endif -/* FIH } */ - return err; + return 0; } - -/* Writes one byte to given address in mXT chip. */ - -static int mxt_write_byte(struct i2c_client *client, u16 addr, u8 value) +static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val) { - - struct mxt_data *mxt; - struct mxt_i2c_byte_transfer i2c_byte_transfer; - int err; - - mxt = i2c_get_clientdata(client); - if (mxt != NULL) - mxt->last_read_addr = -1; - i2c_byte_transfer.le_addr = cpu_to_le16(addr); - i2c_byte_transfer.data = value; - - if (i2c_master_send(client, (u8 *) &i2c_byte_transfer, 3) == 3) - err = 0; - else - err = -EIO; - - return err; + return __mxt_read_reg(client, reg, 1, val); } -/* Writes a block of bytes (max 256) to given address in mXT chip. */ -static int mxt_write_block(struct i2c_client *client, - u16 addr, u16 length, u8 *value) +static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val) { - int i; - struct { - __le16 le_addr; - u8 data[256]; - } i2c_block_transfer; - struct mxt_data *mxt; - - dev_dbg(&client->dev, "Writing %d bytes to %d...", length, addr); - if (length > 256) - return -EINVAL; + u8 buf[3]; - mxt = i2c_get_clientdata(client); - if (mxt != NULL) - mxt->last_read_addr = -1; + buf[0] = reg & 0xff; + buf[1] = (reg >> 8) & 0xff; + buf[2] = val; - memcpy(i2c_block_transfer.data, value, length); - i2c_block_transfer.le_addr = cpu_to_le16(addr); - i = i2c_master_send(client, (u8 *) &i2c_block_transfer, length + 2); - if (i == (length + 2)) - return length; - else + if (i2c_master_send(client, buf, 3) != 3) { + dev_err(&client->dev, "%s: i2c send failed\n", __func__); return -EIO; + } + + return 0; } -/* Calculates the CRC value for mXT infoblock. */ -int calculate_infoblock_crc(u32 *crc_result, u8 *data, int crc_area_size) +static int mxt_read_object_table(struct i2c_client *client, + u16 reg, u8 *object_buf) { - u32 crc = 0; - int i; - - pr_debug("atmel_mxt224 In function %s", __func__); - for (i = 0; i < (crc_area_size - 1); i = i + 2) - crc = CRC_24(crc, *(data + i), *(data + i + 1)); - /* If uneven size, pad with zero */ - if (crc_area_size & 0x0001) - crc = CRC_24(crc, *(data + i), 0); - /* Return only 24 bits of CRC. */ - *crc_result = (crc & 0x00FFFFFF); - - return 0; + return __mxt_read_reg(client, reg, MXT_OBJECT_SIZE, + object_buf); } -static void report_mt(struct mxt_data *mxt) +static struct mxt_object * +mxt_get_object(struct mxt_data *data, u8 type) { + struct mxt_object *object; int i; - int active_touches = 0; - - for (i = 0; i < mxt->numtouch; i++) { - if (!stored_size[i]) - continue; - active_touches++; - input_report_abs(mxt->touch_input, - ABS_MT_TRACKING_ID, - i); - input_report_abs(mxt->touch_input, - ABS_MT_TOUCH_MAJOR, - stored_size[i]); - input_report_abs(mxt->touch_input, - ABS_MT_POSITION_X, - stored_x[i]); - input_report_abs(mxt->touch_input, - ABS_MT_POSITION_Y, - stored_y[i]); - input_mt_sync(mxt->touch_input); + for (i = 0; i < data->info.object_num; i++) { + object = data->object_table + i; + if (object->type == type) + return object; } - if (active_touches == 0) - input_mt_sync(mxt->touch_input); - input_sync(mxt->touch_input); + dev_err(&data->client->dev, "Invalid object type\n"); + return NULL; } -static void process_T9_message(u8 *message, struct mxt_data *mxt) +static int mxt_read_message(struct mxt_data *data, + struct mxt_message *message) { - struct input_dev *input; - struct device *dev = &mxt->client->dev; - u8 status; - u16 xpos = 0xFFFF; - u16 ypos = 0xFFFF; - u8 touch_size = 255; - u8 touch_number; - u8 amplitude; - u8 report_id; - input = mxt->touch_input; - status = message[MXT_MSG_T9_STATUS]; - report_id = message[0]; - - if (status & MXT_MSGB_T9_SUPPRESS) { - /* Touch has been suppressed by grip/face */ - /* detection */ - dev_dbg(&mxt->client->dev, "SUPRESS"); - } else { -/* FIH { */ -/* Correct coordinate */ -#if 0 - xpos = message[MXT_MSG_T9_XPOSMSB] * 16 + - ((message[MXT_MSG_T9_XYPOSLSB] >> 4) & 0xF); - ypos = message[MXT_MSG_T9_YPOSMSB] * 16 + - ((message[MXT_MSG_T9_XYPOSLSB] >> 0) & 0xF); - printk(KERN_INFO "[TOUCH] X=%d, Y=%d\n", xpos, ypos); - - if (mxt->max_x_val < 1024) - xpos = xpos >> 2; - - if (mxt->max_y_val < 1024) - ypos = ypos >> 2; - - printk(KERN_INFO "[TOUCH] [X=%d, Y=%d] max_x=%d , max_y=%d\n", xpos, ypos, mxt->max_x_val, mxt->max_y_val); -#else - xpos = message[MXT_MSG_T9_XPOSMSB] * 16 + - ((message[MXT_MSG_T9_XYPOSLSB] >> 4) & 0xF); - ypos = message[MXT_MSG_T9_YPOSMSB] * 4 + - ((message[MXT_MSG_T9_XYPOSLSB] >> 6) & 0x3); - printk(KERN_INFO "[TOUCH] X=%d, Y=%d\n", xpos, ypos); - -#if 0 - xpos = xpos*1024*9/12800 + 51; - ypos = ypos*1024*9/8000 + 51; - printk(KERN_INFO "[TOUCH] [X=%d, Y=%d]\n", xpos, ypos); -#else - xpos = (xpos)*1024/1280; - if (xpos > 1024) - xpos = 1024; - if (xpos < 0) - xpos = 0; - ypos = (ypos)*1024/800; - if (ypos > 1024) - ypos = 1024; - if (ypos < 0) - ypos = 0; - printk(KERN_INFO "[TOUCH] [X=%d, Y=%d]\n", xpos, ypos); -#endif + struct mxt_object *object; + u16 reg; -#endif + object = mxt_get_object(data, MXT_GEN_MESSAGE); + if (!object) + return -EINVAL; + reg = object->start_address; + return __mxt_read_reg(data->client, reg, + sizeof(struct mxt_message), message); +} +static int mxt_read_object(struct mxt_data *data, + u8 type, u8 offset, u8 *val) +{ + struct mxt_object *object; + u16 reg; + object = mxt_get_object(data, type); + if (!object) + return -EINVAL; -/* FIH } */ + reg = object->start_address; + return __mxt_read_reg(data->client, reg + offset, 1, val); +} - touch_number = message[MXT_MSG_REPORTID] - - mxt->rid_map[report_id].first_rid; +static int mxt_write_object(struct mxt_data *data, + u8 type, u8 offset, u8 val) +{ + struct mxt_object *object; + u16 reg; - stored_x[touch_number] = xpos; - stored_y[touch_number] = ypos; + object = mxt_get_object(data, type); + if (!object) + return -EINVAL; - if (status & MXT_MSGB_T9_DETECT) { - /* - * TODO: more precise touch size calculation? - * mXT224 reports the number of touched nodes, - * so the exact value for touch ellipse major - * axis length would be 2*sqrt(touch_size/pi) - * (assuming round touch shape). - */ - touch_size = message[MXT_MSG_T9_TCHAREA]; - touch_size = touch_size >> 2; - if (!touch_size) - touch_size = 1; - stored_size[touch_number] = touch_size; - if (status & MXT_MSGB_T9_AMP) - /* Amplitude of touch has changed */ - amplitude = message[MXT_MSG_T9_TCHAMPLITUDE]; + reg = object->start_address; + return mxt_write_reg(data->client, reg + offset, val); +} - printk(KERN_INFO, "DETECT:%s%s%s%s", - ((status & MXT_MSGB_T9_PRESS) ? " PRESS" : ""), - ((status & MXT_MSGB_T9_MOVE) ? " MOVE" : ""), - ((status & MXT_MSGB_T9_AMP) ? " AMP" : ""), - ((status & MXT_MSGB_T9_VECTOR) ? " VECT" : "")); - } else if (status & MXT_MSGB_T9_RELEASE) { - printk(KERN_INFO, "RELEASE"); +static void mxt_input_report(struct mxt_data *data, int single_id) +{ + struct mxt_finger *finger = data->finger; + struct input_dev *input_dev = data->input_dev; + int status = finger[single_id].status; + int finger_num = 0; + int id; + + for (id = 0; id < MXT_MAX_FINGER; id++) { + if (!finger[id].status) + continue; - /* The previously reported touch has been removed.*/ - stored_size[touch_number] = 0; + input_mt_slot(input_dev, id); + input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, + finger[id].status != MXT_RELEASE); + + if (finger[id].status != MXT_RELEASE) { + finger_num++; + input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, + finger[id].area); + input_report_abs(input_dev, ABS_MT_POSITION_X, + finger[id].x); + input_report_abs(input_dev, ABS_MT_POSITION_Y, + finger[id].y); + } else { + finger[id].status = 0; } + } + + input_report_key(input_dev, BTN_TOUCH, finger_num > 0); - printk(KERN_INFO, "X=%d, Y=%d, touch number=%d, TOUCHSIZE=%d", - xpos, ypos, touch_number, stored_size[touch_number]); + if (status != MXT_RELEASE) { + input_report_abs(input_dev, ABS_X, finger[single_id].x); + input_report_abs(input_dev, ABS_Y, finger[single_id].y); } + + input_sync(input_dev); } -void process_key_message(u8 *message, struct mxt_data *mxt) +static void mxt_input_touchevent(struct mxt_data *data, + struct mxt_message *message, int id) { - /*key up*/ - if (message[1] == 0 && message[2] == 0 && message[3] == 0 && message[4] == 0) { - if (mxt->prev_key == 0) { - dev_dbg(&mxt->client->dev, "No previous key"); - } else { - input_report_key(mxt->key_input, mxt->prev_key, 0); - dev_dbg(&mxt->client->dev, - "Report key %d up", mxt->prev_key); - mxt->prev_key = 0; + struct mxt_finger *finger = data->finger; + struct device *dev = &data->client->dev; + u8 status = message->message[0]; + int x; + int y; + int area; + + /* Check the touch is present on the screen */ + if (!(status & MXT_DETECT)) { + if (status & MXT_RELEASE) { + dev_dbg(dev, "[%d] released\n", id); + + finger[id].status = MXT_RELEASE; + mxt_input_report(data, id); } - input_sync(mxt->key_input); return; } -printk(KERN_INFO "message[1]=%d, message[2]=%d, message[3]=%d, message[4]=%d", message[1], message[2], message[3], message[4]); - - /*key down*/ - if (message[1] == 128 && message[2] == 0 && message[3] == 2 && message[4] == 0) { - input_report_key(mxt->key_input, KEY_BACK, 1); - dev_dbg(&mxt->client->dev, - "Report BACK(%d) key DOWN.", KEY_BACK); - mxt->prev_key = KEY_BACK; - } else if (message[1] == 128 && message[2] == 0 && message[3] == 4 && message[4] == 0) { - input_report_key(mxt->key_input, KEY_MENU, 1); - dev_dbg(&mxt->client->dev, - "Report MENU(%d) key DOWN.", KEY_MENU); - mxt->prev_key = KEY_MENU; - } else if (message[1] == 128 && message[2] == 0 && message[3] == 8 && message[4] == 0) { - input_report_key(mxt->key_input, KEY_HOME, 1); - dev_dbg(&mxt->client->dev, - "Report HOME(%d) key DOWN.", KEY_HOME); - mxt->prev_key = KEY_HOME; - } else if (message[1] == 128 && message[2] == 8 && message[3] == 0 && message[4] == 0) { - input_report_key(mxt->key_input, KEY_SEARCH, 1); - dev_dbg(&mxt->client->dev, - "Report SEARCH(%d) key DOWN.", KEY_SEARCH); - mxt->prev_key = KEY_SEARCH; - } - input_sync(mxt->key_input); -} + /* Check only AMP detection */ + if (!(status & (MXT_PRESS | MXT_MOVE))) + return; -static int process_message(u8 *message, u8 object, struct mxt_data *mxt) -{ - struct i2c_client *client; - u8 status; - u16 xpos = 0xFFFF; - u16 ypos = 0xFFFF; - u8 event; - u8 direction; - u16 distance; - u8 length; - u8 report_id; - static u8 error_cond; - client = mxt->client; - length = mxt->message_size; - report_id = message[0]; - - switch (object) { - case MXT_GEN_COMMANDPROCESSOR_T6: - status = message[1]; - - if (status & MXT_MSGB_T6_COMSERR) { - if ((!error_cond) & MXT_MSGB_T6_COMSERR) { - dev_err(&client->dev, "maXTouch checksum error\n"); - error_cond |= MXT_MSGB_T6_COMSERR; - } - } - if (status & MXT_MSGB_T6_CFGERR) { - /* - * Configuration error. A proper configuration - * needs to be written to chip and backed up. Refer - * to protocol document for further info. - */ - if ((!error_cond) & MXT_MSGB_T6_CFGERR) { - dev_err(&client->dev, "maXTouch configuration error\n"); - error_cond |= MXT_MSGB_T6_CFGERR; - } - } - if (status & MXT_MSGB_T6_CAL) { - /* Calibration in action, no need to react */ - dev_info(&client->dev, "maXTouch calibration in progress\n"); - } - if (status & MXT_MSGB_T6_SIGERR) { - /* - * Signal acquisition error, something is seriously - * wrong, not much we can in the driver to correct - * this - */ - if ((!error_cond) & MXT_MSGB_T6_SIGERR) { - dev_err(&client->dev, "maXTouch acquisition error\n"); - error_cond |= MXT_MSGB_T6_SIGERR; - } - } - if (status & MXT_MSGB_T6_OFL) { - /* - * Cycle overflow, the acquisition is too short. - * Can happen temporarily when there's a complex - * touch shape on the screen requiring lots of - * processing. - */ - dev_err(&client->dev, "maXTouch cycle overflow\n"); - } - if (status & MXT_MSGB_T6_RESET) { - /* Chip has reseted, no need to react. */ - dev_info(&client->dev, "maXTouch chip reset\n"); - } - if (status == 0) { - /* Chip status back to normal. */ - dev_info(&client->dev, "maXTouch status normal\n"); - error_cond = 0; - } - break; + x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf); + y = (message->message[2] << 4) | ((message->message[3] & 0xf)); + if (data->max_x < 1024) + x = x >> 2; + if (data->max_y < 1024) + y = y >> 2; - case MXT_TOUCH_KEYARRAY_T15: - dev_dbg(&client->dev, "key value, message[1]=%d, " - "message[2]=%d, message[3]=%d, message[4]=%d", - message[1], message[2], message[3], message[4]); - process_key_message(message, mxt); - break; + area = message->message[4]; - case MXT_TOUCH_MULTITOUCHSCREEN_T9: - process_T9_message(message, mxt); - report_mt(mxt); - break; + dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id, + status & MXT_MOVE ? "moved" : "pressed", + x, y, area); - case MXT_SPT_GPIOPWM_T19: - if (debug >= DEBUG_TRACE) - dev_info(&client->dev, "Receiving GPIO message\n"); - break; + finger[id].status = status & MXT_MOVE ? + MXT_MOVE : MXT_PRESS; + finger[id].x = x; + finger[id].y = y; + finger[id].area = area; - case MXT_PROCI_GRIPFACESUPPRESSION_T20: - if (debug >= DEBUG_TRACE) - dev_info(&client->dev, "Receiving face suppression msg\n"); - break; + mxt_input_report(data, id); +} - case MXT_PROCG_NOISESUPPRESSION_T22: - if (debug >= DEBUG_TRACE) - dev_info(&client->dev, "Receiving noise suppression msg\n"); - status = message[MXT_MSG_T22_STATUS]; - if (status & MXT_MSGB_T22_FHCHG) { - if (debug >= DEBUG_TRACE) - dev_info(&client->dev, "maXTouch: Freq changed\n"); - } - if (status & MXT_MSGB_T22_GCAFERR) { - if (debug >= DEBUG_TRACE) - dev_info(&client->dev, "maXTouch: High noise level\n"); - } - if (status & MXT_MSGB_T22_FHERR) { - if (debug >= DEBUG_TRACE) - dev_info(&client->dev, - "maXTouch: Freq changed - Noise level too high\n"); +static irqreturn_t mxt_interrupt(int irq, void *dev_id) +{ + struct mxt_data *data = dev_id; + struct mxt_message message; + struct mxt_object *object; + struct device *dev = &data->client->dev; + int id; + u8 reportid; + u8 max_reportid; + u8 min_reportid; + + do { + if (mxt_read_message(data, &message)) { + dev_err(dev, "Failed to read message\n"); + goto end; } - break; - case MXT_PROCI_ONETOUCHGESTUREPROCESSOR_T24: - if (debug >= DEBUG_TRACE) - dev_info(&client->dev, - "Receiving one-touch gesture msg\n"); - - event = message[MXT_MSG_T24_STATUS] & 0x0F; - xpos = message[MXT_MSG_T24_XPOSMSB] * 16 + - ((message[MXT_MSG_T24_XYPOSLSB] >> 4) & 0x0F); - ypos = message[MXT_MSG_T24_YPOSMSB] * 16 + - ((message[MXT_MSG_T24_XYPOSLSB] >> 0) & 0x0F); - xpos >>= 2; - ypos >>= 2; - direction = message[MXT_MSG_T24_DIR]; - distance = message[MXT_MSG_T24_DIST] + - (message[MXT_MSG_T24_DIST + 1] << 16); - - input_event(mxt->touch_input, EV_MSC, MSC_GESTURE, - (event << 24) | (direction << 16) | distance); - input_event(mxt->touch_input, EV_MSC, MSC_GESTURE, - (xpos << 16) | ypos); - break; + reportid = message.reportid; - case MXT_SPT_SELFTEST_T25: - if (debug >= DEBUG_TRACE) - dev_info(&client->dev, - "Receiving Self-Test msg\n"); - - if (message[MXT_MSG_T25_STATUS] == MXT_MSGR_T25_RUN_ALL_TESTS) { - if (debug >= DEBUG_TRACE) - dev_info(&client->dev, - "maXTouch: Self-Test OK\n"); - - } else { - dev_err(&client->dev, - "maXTouch: Self-Test Failed [%02x]:" - "{%02x,%02x,%02x,%02x,%02x}\n", - message[MXT_MSG_T25_STATUS], - message[MXT_MSG_T25_STATUS + 0], - message[MXT_MSG_T25_STATUS + 1], - message[MXT_MSG_T25_STATUS + 2], - message[MXT_MSG_T25_STATUS + 3], - message[MXT_MSG_T25_STATUS + 4] - ); - } - break; + /* whether reportid is thing of MXT_TOUCH_MULTI */ + object = mxt_get_object(data, MXT_TOUCH_MULTI); + if (!object) + goto end; - case MXT_PROCI_TWOTOUCHGESTUREPROCESSOR_T27: - if (debug >= DEBUG_TRACE) - dev_info(&client->dev, "Receiving 2-touch gesture message\n"); - - event = message[MXT_MSG_T27_STATUS] & 0xF0; - xpos = message[MXT_MSG_T27_XPOSMSB] * 16 + - ((message[MXT_MSG_T27_XYPOSLSB] >> 4) & 0x0F); - ypos = message[MXT_MSG_T27_YPOSMSB] * 16 + - ((message[MXT_MSG_T27_XYPOSLSB] >> 0) & 0x0F); - xpos >>= 2; - ypos >>= 2; - direction = message[MXT_MSG_T27_ANGLE]; - distance = message[MXT_MSG_T27_SEPARATION] + - (message[MXT_MSG_T27_SEPARATION + 1] << 16); - - input_event(mxt->touch_input, EV_MSC, MSC_GESTURE, - (event << 24) | (direction << 16) | distance); - input_event(mxt->touch_input, EV_MSC, MSC_GESTURE, - (xpos << 16) | ypos); - break; - case MXT_SPT_CTECONFIG_T28: - if (debug >= DEBUG_TRACE) - dev_info(&client->dev, "Receiving CTE message...\n"); - status = message[MXT_MSG_T28_STATUS]; - if (status & MXT_MSGB_T28_CHKERR) - dev_err(&client->dev, "maXTouch: Power-Up CRC failure\n"); - break; - default: - if (debug >= DEBUG_TRACE) - dev_info(&client->dev, "maXTouch: Unknown message!\n"); - break; - } + max_reportid = object->max_reportid; + min_reportid = max_reportid - object->num_report_ids + 1; + id = reportid - min_reportid; - return 0; + if (reportid >= min_reportid && reportid <= max_reportid) + mxt_input_touchevent(data, &message, id); + else + mxt_dump_message(dev, &message); + } while (reportid != 0xff); + +end: + return IRQ_HANDLED; } -/* - * Processes messages when the interrupt line (CHG) is asserted. Keeps - * reading messages until a message with report ID 0xFF is received, - * which indicates that there is no more new messages. - * - */ -static void mxt_worker(struct mxt_data *mxt) +static int mxt_check_reg_init(struct mxt_data *data) { - struct i2c_client *client; - u8 *message; - u16 message_length; - u16 message_addr; - u8 report_id; - u8 object; - int error; - int i; - int intr_value; - - client = mxt->client; - message = mxt->message_buf; - message_addr = mxt->msg_proc_addr; - message_length = mxt->message_size; - - if (message_length >= 256) { - dev_err(&client->dev, "Message length > 256 bytes not supported\n"); - return; + const struct mxt_platform_data *pdata = data->pdata; + struct mxt_object *object; + struct device *dev = &data->client->dev; + int index = 0; + int i, j, config_offset; + + if (!pdata->config) { + dev_dbg(dev, "No cfg data defined, skipping reg init\n"); + return 0; } - dev_dbg(&client->dev, "maXTouch worker active:\n"); - do { - /* Read next message, reread on failure. */ - mxt->message_counter++; - for (i = 1; i < I2C_RETRY_COUNT; i++) { - error = mxt_read_block(client, message_addr, - message_length - 1, message); - if (error >= 0) - break; - mxt->read_fail_counter++; - dev_err(&client->dev, "Failure reading maxTouch device\n"); - } - if (error < 0) - return; - - report_id = message[0]; - - if (reg_add > 0) - dev_info( - &client->dev, - "Atmel Debug info message[0]=%d,message[1]=%d,message[2]=%d,message[3]=%d" - "message[4]=%d,message[5]=%d,message[6]=%d,message[7]=%d,message_length=%d", - message[0], message[1], message[2], message[3], - message[4], message[5], message[6], message[7], message_length); - - if ((report_id != MXT_END_OF_MESSAGES) && (report_id != 0)) { - /* Get type of object and process the message */ - object = mxt->rid_map[report_id].object; - process_message(message, object, mxt); + for (i = 0; i < data->info.object_num; i++) { + object = data->object_table + i; + + if (!mxt_object_writable(object->type)) + continue; + + for (j = 0; j < object->size + 1; j++) { + config_offset = index + j; + if (config_offset > pdata->config_length) { + dev_err(dev, "Not enough config data!\n"); + return -EINVAL; + } + mxt_write_object(data, object->type, j, + pdata->config[config_offset]); } - /*dev_dbg(&client->dev, "chgline: %d\n", mxt->read_chg());*/ - intr_value = gpio_get_value(mxt->mxt_intr_gpio); - } while (intr_value == 0); + index += object->size + 1; + } + + return 0; } -/* - * The maXTouch device will signal the host about a new message by asserting - * the CHG line. This ISR schedules a worker routine to read the message when - * that happens. - */ -static irqreturn_t mxt_irq_handler(int irq, void *_mxt) +static int mxt_make_highchg(struct mxt_data *data) { - struct mxt_data *mxt = _mxt; - - mxt->irq_counter++; - if (mxt->valid_interrupt()) { - mxt->valid_irq_counter++; + struct device *dev = &data->client->dev; + struct mxt_message message; + int count = 10; + int error; - mutex_lock(&mxt->dev_mutex); - mxt_worker(mxt); - mutex_unlock(&mxt->dev_mutex); - } else { - mxt->invalid_irq_counter++; - return IRQ_NONE; + /* Read dummy message to make high CHG pin */ + do { + error = mxt_read_message(data, &message); + if (error) + return error; + } while (message.reportid != 0xff && --count); + + if (!count) { + dev_err(dev, "CHG pin isn't cleared\n"); + return -EBUSY; } - return IRQ_HANDLED; + return 0; } -/******************************************************************************/ -/* Initialization of driver */ -/******************************************************************************/ +static void mxt_handle_pdata(struct mxt_data *data) +{ + const struct mxt_platform_data *pdata = data->pdata; + u8 voltage; + + /* Set touchscreen lines */ + mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_XSIZE, + pdata->x_line); + mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_YSIZE, + pdata->y_line); + + /* Set touchscreen orient */ + mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_ORIENT, + pdata->orient); + + /* Set touchscreen burst length */ + mxt_write_object(data, MXT_TOUCH_MULTI, + MXT_TOUCH_BLEN, pdata->blen); + + /* Set touchscreen threshold */ + mxt_write_object(data, MXT_TOUCH_MULTI, + MXT_TOUCH_TCHTHR, pdata->threshold); + + /* Set touchscreen resolution */ + mxt_write_object(data, MXT_TOUCH_MULTI, + MXT_TOUCH_XRANGE_LSB, (pdata->x_size - 1) & 0xff); + mxt_write_object(data, MXT_TOUCH_MULTI, + MXT_TOUCH_XRANGE_MSB, (pdata->x_size - 1) >> 8); + mxt_write_object(data, MXT_TOUCH_MULTI, + MXT_TOUCH_YRANGE_LSB, (pdata->y_size - 1) & 0xff); + mxt_write_object(data, MXT_TOUCH_MULTI, + MXT_TOUCH_YRANGE_MSB, (pdata->y_size - 1) >> 8); + + /* Set touchscreen voltage */ + if (pdata->voltage) { + if (pdata->voltage < MXT_VOLTAGE_DEFAULT) { + voltage = (MXT_VOLTAGE_DEFAULT - pdata->voltage) / + MXT_VOLTAGE_STEP; + voltage = 0xff - voltage + 1; + } else + voltage = (pdata->voltage - MXT_VOLTAGE_DEFAULT) / + MXT_VOLTAGE_STEP; + + mxt_write_object(data, MXT_SPT_CTECONFIG, + MXT_CTE_VOLTAGE, voltage); + } +} -static int __devinit mxt_identify(struct i2c_client *client, - struct mxt_data *mxt, - u8 *id_block_data) +static int mxt_get_info(struct mxt_data *data) { - u8 buf[7]; + struct i2c_client *client = data->client; + struct mxt_info *info = &data->info; int error; - int identified; + u8 val; - identified = 0; + error = mxt_read_reg(client, MXT_FAMILY_ID, &val); + if (error) + return error; + info->family_id = val; - /* Read Device info to check if chip is valid */ - error = mxt_read_block(client, MXT_ADDR_INFO_BLOCK, MXT_ID_BLOCK_SIZE, - (u8 *) buf); + error = mxt_read_reg(client, MXT_VARIANT_ID, &val); + if (error) + return error; + info->variant_id = val; - if (error < 0) { - client->addr = MXT1386_I2C_ADDR2; - slave_addr = MXT1386_I2C_ADDR2; - printk(KERN_INFO "[TOUCH] switch slave address to 0x%02x", client->addr); - error = mxt_read_block(client, MXT_ADDR_INFO_BLOCK, MXT_ID_BLOCK_SIZE, (u8 *) buf); - } + error = mxt_read_reg(client, MXT_VERSION, &val); + if (error) + return error; + info->version = val; - if (error < 0) { - mxt->read_fail_counter++; - dev_err(&client->dev, "Failure accessing maXTouch device\n"); - return -EIO; - } + error = mxt_read_reg(client, MXT_BUILD, &val); + if (error) + return error; + info->build = val; - memcpy(id_block_data, buf, MXT_ID_BLOCK_SIZE); - - mxt->device_info.family_id = buf[0]; - mxt->device_info.variant_id = buf[1]; - mxt->device_info.major = ((buf[2] >> 4) & 0x0F); - mxt->device_info.minor = (buf[2] & 0x0F); - mxt->device_info.build = buf[3]; - mxt->device_info.x_size = buf[4]; - mxt->device_info.y_size = buf[5]; - mxt->device_info.num_objs = buf[6]; - mxt->device_info.num_nodes = mxt->device_info.x_size * - mxt->device_info.y_size; - - /* - * Check Family & Variant Info; warn if not recognized but - * still continue. - */ - - /* MXT224 */ - if (mxt->device_info.family_id == MXT224_FAMILYID) { - strcpy(mxt->device_info.family_name, "atmel_mxt224"); - - if (mxt->device_info.variant_id == MXT224_CAL_VARIANTID) { - strcpy(mxt->device_info.variant_name, "Calibrated"); - } else if (mxt->device_info.variant_id == - MXT224_UNCAL_VARIANTID) { - strcpy(mxt->device_info.variant_name, "Uncalibrated"); - } else { - dev_err(&client->dev, - "Warning: maXTouch Variant ID [%d] not supported\n", - mxt->device_info.variant_id); - strcpy(mxt->device_info.variant_name, "UNKNOWN"); - /* identified = -ENXIO; */ - } + error = mxt_read_reg(client, MXT_OBJECT_NUM, &val); + if (error) + return error; + info->object_num = val; - /* MXT1386 */ - } else if (mxt->device_info.family_id == MXT1386_FAMILYID) { -/* FIH { */ -#if 0 - strcpy(mxt->device_info.family_name, "mXT1386"); -#else - strcpy(mxt->device_info.family_name, "mxt1386"); -#endif -/* FIH } */ + return 0; +} - if (mxt->device_info.variant_id == MXT1386_CAL_VARIANTID) { - strcpy(mxt->device_info.variant_name, "Calibrated"); - } else { - dev_err(&client->dev, - "Warning: maXTouch Variant ID [%d] not " - "supported\n", - mxt->device_info.variant_id); - strcpy(mxt->device_info.variant_name, "UNKNOWN"); - /* identified = -ENXIO; */ +static int mxt_get_object_table(struct mxt_data *data) +{ + int error; + int i; + u16 reg; + u8 reportid = 0; + u8 buf[MXT_OBJECT_SIZE]; + + for (i = 0; i < data->info.object_num; i++) { + struct mxt_object *object = data->object_table + i; + + reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i; + error = mxt_read_object_table(data->client, reg, buf); + if (error) + return error; + + object->type = buf[0]; + object->start_address = (buf[2] << 8) | buf[1]; + object->size = buf[3]; + object->instances = buf[4]; + object->num_report_ids = buf[5]; + + if (object->num_report_ids) { + reportid += object->num_report_ids * + (object->instances + 1); + object->max_reportid = reportid; } - /* Unknown family ID! */ - } else { - dev_err(&client->dev, - "Warning: maXTouch Family ID [%d] not supported\n", - mxt->device_info.family_id); - strcpy(mxt->device_info.family_name, "UNKNOWN"); - strcpy(mxt->device_info.variant_name, "UNKNOWN"); - /* identified = -ENXIO; */ } - dev_info( - &client->dev, - "Atmel maXTouch (Family %s (%X), Variant %s (%X)) Firmware " - "version [%d.%d] Build %d\n", - mxt->device_info.family_name, - mxt->device_info.family_id, - mxt->device_info.variant_name, - mxt->device_info.variant_id, - mxt->device_info.major, - mxt->device_info.minor, - mxt->device_info.build - ); - dev_info( - &client->dev, - "Atmel maXTouch Configuration " - "[X: %d] x [Y: %d]\n", - mxt->device_info.x_size, - mxt->device_info.y_size - ); - return identified; + return 0; } -/* - * Reads the object table from maXTouch chip to get object data like - * address, size, report id. For Info Block CRC calculation, already read - * id data is passed to this function too (Info Block consists of the ID - * block and object table). - * - */ -static int __devinit mxt_read_object_table(struct i2c_client *client, - struct mxt_data *mxt, - u8 *raw_id_data) +static int mxt_initialize(struct mxt_data *data) { - u16 report_id_count; - u8 buf[MXT_OBJECT_TABLE_ELEMENT_SIZE]; - u8 *raw_ib_data; - u8 object_type; - u16 object_address; - u16 object_size; - u8 object_instances; - u8 object_report_ids; - u16 object_info_address; - u32 crc; - u32 calculated_crc; - int i; - int error; - - u8 object_instance; - u8 object_report_id; - u8 report_id; - int first_report_id; - int ib_pointer; - struct mxt_object *object_table; - dev_dbg(&mxt->client->dev, "maXTouch driver reading configuration\n"); - - object_table = kzalloc(sizeof(struct mxt_object) * - mxt->device_info.num_objs, - GFP_KERNEL); - if (object_table == NULL) { - printk(KERN_WARNING "maXTouch: Memory allocation failed!\n"); - error = -ENOMEM; - goto err_object_table_alloc; + struct i2c_client *client = data->client; + struct mxt_info *info = &data->info; + int error; + u8 val; + + error = mxt_get_info(data); + if (error) + return error; + + data->object_table = kcalloc(info->object_num, + sizeof(struct mxt_object), + GFP_KERNEL); + if (!data->object_table) { + dev_err(&client->dev, "Failed to allocate memory\n"); + return -ENOMEM; } - raw_ib_data = kmalloc(MXT_OBJECT_TABLE_ELEMENT_SIZE * - mxt->device_info.num_objs + MXT_ID_BLOCK_SIZE, - GFP_KERNEL); - if (raw_ib_data == NULL) { - printk(KERN_WARNING "maXTouch: Memory allocation failed!\n"); - error = -ENOMEM; - goto err_ib_alloc; - } + /* Get object table information */ + error = mxt_get_object_table(data); + if (error) + return error; + + /* Check register init values */ + error = mxt_check_reg_init(data); + if (error) + return error; + + mxt_handle_pdata(data); + + /* Backup to memory */ + mxt_write_object(data, MXT_GEN_COMMAND, + MXT_COMMAND_BACKUPNV, + MXT_BACKUP_VALUE); + msleep(MXT_BACKUP_TIME); + + /* Soft reset */ + mxt_write_object(data, MXT_GEN_COMMAND, + MXT_COMMAND_RESET, 1); + msleep(MXT_RESET_TIME); + + /* Update matrix size at info struct */ + error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val); + if (error) + return error; + info->matrix_xsize = val; + + error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val); + if (error) + return error; + info->matrix_ysize = val; + + dev_info(&client->dev, + "Family ID: %d Variant ID: %d Version: %d Build: %d\n", + info->family_id, info->variant_id, info->version, + info->build); + + dev_info(&client->dev, + "Matrix X Size: %d Matrix Y Size: %d Object Num: %d\n", + info->matrix_xsize, info->matrix_ysize, + info->object_num); - /* Copy the ID data for CRC calculation. */ - memcpy(raw_ib_data, raw_id_data, MXT_ID_BLOCK_SIZE); - ib_pointer = MXT_ID_BLOCK_SIZE; + return 0; +} - mxt->object_table = object_table; +static void mxt_calc_resolution(struct mxt_data *data) +{ + unsigned int max_x = data->pdata->x_size - 1; + unsigned int max_y = data->pdata->y_size - 1; - dev_dbg(&mxt->client->dev, "maXTouch driver Memory allocated\n"); + if (data->pdata->orient & MXT_XY_SWITCH) { + data->max_x = max_y; + data->max_y = max_x; + } else { + data->max_x = max_x; + data->max_y = max_y; + } +} - object_info_address = MXT_ADDR_OBJECT_TABLE; +static ssize_t mxt_object_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mxt_data *data = dev_get_drvdata(dev); + struct mxt_object *object; + int count = 0; + int i, j; + int error; + u8 val; - report_id_count = 0; - for (i = 0; i < mxt->device_info.num_objs; i++) { - dev_dbg(&mxt->client->dev, "Reading maXTouch at [0x%04x]: ", - object_info_address); + for (i = 0; i < data->info.object_num; i++) { + object = data->object_table + i; - error = mxt_read_block(client, object_info_address, - MXT_OBJECT_TABLE_ELEMENT_SIZE, buf); + count += sprintf(buf + count, + "Object Table Element %d(Type %d)\n", + i + 1, object->type); - if (error < 0) { - mxt->read_fail_counter++; - dev_err(&client->dev, - "maXTouch Object %d could not be read\n", i); - error = -EIO; - goto err_object_read; + if (!mxt_object_readable(object->type)) { + count += sprintf(buf + count, "\n"); + continue; } - memcpy(raw_ib_data + ib_pointer, buf, - MXT_OBJECT_TABLE_ELEMENT_SIZE); - ib_pointer += MXT_OBJECT_TABLE_ELEMENT_SIZE; - - object_type = buf[0]; - object_address = (buf[2] << 8) + buf[1]; - object_size = buf[3] + 1; - object_instances = buf[4] + 1; - object_report_ids = buf[5]; - dev_dbg(&mxt->client->dev, "Type=%03d, Address=0x%04x, " - "Size=0x%02x, %d instances, %d report id's\n", - object_type, - object_address, - object_size, - object_instances, - object_report_ids - ); - - /* TODO: check whether object is known and supported? */ - - /* Save frequently needed info. */ - if (object_type == MXT_GEN_MESSAGEPROCESSOR_T5) { - mxt->msg_proc_addr = object_address; - mxt->message_size = object_size; - } + for (j = 0; j < object->size + 1; j++) { + error = mxt_read_object(data, + object->type, j, &val); + if (error) + return error; - object_table[i].type = object_type; - object_table[i].chip_addr = object_address; - object_table[i].size = object_size; - object_table[i].instances = object_instances; - object_table[i].num_report_ids = object_report_ids; - report_id_count += object_instances * object_report_ids; + count += sprintf(buf + count, + " Byte %d: 0x%x (%d)\n", j, val, val); + } - object_info_address += MXT_OBJECT_TABLE_ELEMENT_SIZE; + count += sprintf(buf + count, "\n"); } - mxt->rid_map = - kzalloc(sizeof(struct report_id_map) * (report_id_count + 1), - /* allocate for report_id 0, even if not used */ - GFP_KERNEL); - if (mxt->rid_map == NULL) { - printk(KERN_WARNING "maXTouch: Can't allocate memory!\n"); - error = -ENOMEM; - goto err_rid_map_alloc; - } + return count; +} - mxt->message_buf = kmalloc(256, GFP_KERNEL); - if (mxt->message_buf == NULL) { - printk(KERN_WARNING "Error allocating memory\n"); - error = -ENOMEM; - goto err_msg_alloc3; - } +static int mxt_load_fw(struct device *dev, const char *fn) +{ + struct mxt_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + const struct firmware *fw = NULL; + unsigned int frame_size; + unsigned int pos = 0; + int ret; - mxt->report_id_count = report_id_count; - if (report_id_count > 254) { /* 0 & 255 are reserved */ - dev_err(&client->dev, - "Too many maXTouch report id's [%d]\n", - report_id_count); - error = -ENXIO; - goto err_max_rid; + ret = request_firmware(&fw, fn, dev); + if (ret) { + dev_err(dev, "Unable to open firmware %s\n", fn); + return ret; } - /* Create a mapping from report id to object type */ - report_id = 1; /* Start from 1, 0 is reserved. */ - - /* Create table associating report id's with objects & instances */ - for (i = 0; i < mxt->device_info.num_objs; i++) { - for (object_instance = 0; - object_instance < object_table[i].instances; - object_instance++) { - first_report_id = report_id; - for (object_report_id = 0; - object_report_id < object_table[i].num_report_ids; - object_report_id++) { - mxt->rid_map[report_id].object = - object_table[i].type; - mxt->rid_map[report_id].instance = - object_instance; - mxt->rid_map[report_id].first_rid = - first_report_id; - report_id++; - } - } - } + /* Change to the bootloader mode */ + mxt_write_object(data, MXT_GEN_COMMAND, + MXT_COMMAND_RESET, MXT_BOOT_VALUE); + msleep(MXT_RESET_TIME); - /* Read 3 byte CRC */ - error = mxt_read_block(client, object_info_address, 3, buf); - if (error < 0) { - mxt->read_fail_counter++; - dev_err(&client->dev, "Error reading CRC\n"); - } + /* Change to slave address of bootloader */ + if (client->addr == MXT_APP_LOW) + client->addr = MXT_BOOT_LOW; + else + client->addr = MXT_BOOT_HIGH; - crc = (buf[2] << 16) | (buf[1] << 8) | buf[0]; + ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD); + if (ret) + goto out; - if (calculate_infoblock_crc(&calculated_crc, raw_ib_data, - ib_pointer)) { - printk(KERN_WARNING "Error while calculating CRC!\n"); - calculated_crc = 0; - } - kfree(raw_ib_data); + /* Unlock bootloader */ + mxt_unlock_bootloader(client); - dev_dbg(&mxt->client->dev, "\nReported info block CRC = 0x%6X\n", crc); - dev_dbg(&mxt->client->dev, "Calculated info block CRC = 0x%6X\n\n", - calculated_crc); + while (pos < fw->size) { + ret = mxt_check_bootloader(client, + MXT_WAITING_FRAME_DATA); + if (ret) + goto out; - if (crc == calculated_crc) { - mxt->info_block_crc = crc; - } else { - mxt->info_block_crc = 0; - pr_err("maXTouch: Info block CRC invalid!\n"); - } + frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1)); - if (debug >= DEBUG_VERBOSE) { - - dev_info(&client->dev, "maXTouch: %d Objects\n", - mxt->device_info.num_objs); - - for (i = 0; i < mxt->device_info.num_objs; i++) { - dev_info(&client->dev, "Type:\t\t\t[%d]: %s\n", - object_table[i].type, - obj_typ_name[object_table[i].type]); - dev_info(&client->dev, "\tAddress:\t0x%04X\n", - object_table[i].chip_addr); - dev_info(&client->dev, "\tSize:\t\t%d Bytes\n", - object_table[i].size); - dev_info(&client->dev, "\tInstances:\t%d\n", - object_table[i].instances); - dev_info(&client->dev, "\tReport Id's:\t%d\n", - object_table[i].num_report_ids); - } + /* We should add 2 at frame size as the the firmware data is not + * included the CRC bytes. + */ + frame_size += 2; + + /* Write one frame to device */ + mxt_fw_write(client, fw->data + pos, frame_size); + + ret = mxt_check_bootloader(client, + MXT_FRAME_CRC_PASS); + if (ret) + goto out; + + pos += frame_size; + + dev_dbg(dev, "Updated %d bytes / %zd bytes\n", pos, fw->size); } - return 0; -err_msg_alloc3: - kfree(mxt->message_buf); -err_max_rid: - kfree(mxt->rid_map); -err_rid_map_alloc: -err_object_read: - kfree(raw_ib_data); -err_ib_alloc: - kfree(object_table); -err_object_table_alloc: - return error; -} +out: + release_firmware(fw); + /* Change to slave address of application */ + if (client->addr == MXT_BOOT_LOW) + client->addr = MXT_APP_LOW; + else + client->addr = MXT_APP_HIGH; -static u8 mxt_valid_interrupt_dummy(void) -{ - return 1; + return ret; } -static int __devinit mxt_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static ssize_t mxt_update_fw_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { - struct mxt_data *mxt; - struct mxt_platform_data *pdata; - struct input_dev *touch_input; - struct input_dev *key_input; - u8 *id_data; - int error, gpio_intr, i; - u16 base_addr; - - pr_info("atmel_mxt224: mxt_probe\n"); - - if (client == NULL) { - pr_debug("maXTouch: client == NULL\n"); - return -EINVAL; - } else if (client->adapter == NULL) { - pr_debug("maXTouch: client->adapter == NULL\n"); - return -EINVAL; - } else if (&client->dev == NULL) { - pr_debug("maXTouch: client->dev == NULL\n"); - return -EINVAL; - } else if (&client->adapter->dev == NULL) { - pr_debug("maXTouch: client->adapter->dev == NULL\n"); - return -EINVAL; - } else if (id == NULL) { - pr_debug("maXTouch: id == NULL\n"); - return -EINVAL; - } + struct mxt_data *data = dev_get_drvdata(dev); + int error; - dev_dbg(&client->dev, "maXTouch driver v. %s\n", DRIVER_VERSION); - dev_dbg(&client->dev, "\t \"%s\"\n", client->name); - dev_dbg(&client->dev, "\taddr:\t0x%04x\n", client->addr); - dev_dbg(&client->dev, "\tirq:\t%d\n", client->irq); - dev_dbg(&client->dev, "\tflags:\t0x%04x\n", client->flags); - dev_dbg(&client->dev, "\tadapter:\"%s\"\n", client->adapter->name); - dev_dbg(&client->dev, "\tdevice:\t\"%s\"\n", client->dev.init_name); - - /* Check if the I2C bus supports BYTE transfer */ - error = i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE); - if (!error) { - dev_err(&client->dev, "%s adapter not supported\n", - dev_driver_string(&client->adapter->dev)); - return -ENODEV; - } + disable_irq(data->irq); - dev_dbg(&client->dev, "maXTouch driver functionality OK\n"); + error = mxt_load_fw(dev, MXT_FW_NAME); + if (error) { + dev_err(dev, "The firmware update failed(%d)\n", error); + count = error; + } else { + dev_dbg(dev, "The firmware update succeeded\n"); - /* Allocate structure - we need it to identify device */ - mxt = kzalloc(sizeof(struct mxt_data), GFP_KERNEL); - if (mxt == NULL) { - dev_err(&client->dev, "insufficient memory\n"); - error = -ENOMEM; - goto err_mxt_alloc; - } + /* Wait for reset */ + msleep(MXT_FWRESET_TIME); - id_data = kmalloc(MXT_ID_BLOCK_SIZE, GFP_KERNEL); - if (id_data == NULL) { - dev_err(&client->dev, "insufficient memory\n"); - error = -ENOMEM; - goto err_id_alloc; - } + kfree(data->object_table); + data->object_table = NULL; - touch_input = input_allocate_device(); - if (!touch_input) { - dev_err(&client->dev, "error allocating touch input device\n"); - error = -ENOMEM; - goto err_touch_input_dev_alloc; + mxt_initialize(data); } - key_input = input_allocate_device(); - if (!key_input) { - dev_err(&client->dev, "error allocating key input device"); - error = -ENOMEM; - goto err_key_input_dev_alloc; - } + enable_irq(data->irq); - /* Initialize Platform data */ - pdata = client->dev.platform_data; - if (pdata == NULL) { - dev_err(&client->dev, "platform data is required!\n"); - error = -EINVAL; - goto err_pdata; - } - if (debug >= DEBUG_TRACE) - printk(KERN_INFO "Platform OK: pdata = 0x%08x\n", - (unsigned int) pdata); - - mutex_init(&mxt->dev_mutex); - mxt->read_fail_counter = 0; - mxt->message_counter = 0; - mxt->max_x_val = pdata->max_x; - mxt->max_y_val = pdata->max_y; - mxt->orientation = pdata->orientation; - mxt->mxt_intr_gpio = pdata->irq; - mxt->mxt_reset_gpio = pdata->reset; - - error = gpio_request(mxt->mxt_intr_gpio, 0); - if (error < 0) - pr_err("Failed to request GPIO%d (MaxTouch-interrupt) error=%d\n", - mxt->mxt_intr_gpio, error); - - error = gpio_direction_input(mxt->mxt_intr_gpio); - if (error) { - pr_err("Failed to set interrupt direction, error=%d\n", error); - gpio_free(mxt->mxt_intr_gpio); - } + error = mxt_make_highchg(data); + if (error) + return error; - error = gpio_request(mxt->mxt_reset_gpio, "MaxTouch-reset"); - if (error < 0) - pr_err("Failed to request GPIO%d (MaxTouch-reset) error=%d\n", - mxt->mxt_reset_gpio, error); + return count; +} - error = gpio_direction_output(mxt->mxt_reset_gpio, 1); - if (error) { - pr_info("Failed to set reset direction, error=%d\n", error); - gpio_free(mxt->mxt_reset_gpio); - } +static DEVICE_ATTR(object, 0444, mxt_object_show, NULL); +static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store); - /* maXTouch wants 40mSec minimum after reset to get organized */ - gpio_set_value(mxt->mxt_reset_gpio, 1); - msleep(40); -/* FIH { */ -/* Wait for interrupt and delay for unstable reset status */ -#if 1 -{ - int i = 0; +static struct attribute *mxt_attrs[] = { + &dev_attr_object.attr, + &dev_attr_update_fw.attr, + NULL +}; - for (i = 0; i < 10; i++) { - printk(KERN_INFO "Polling GPIO%d (MaxTouch-intr). retry=%d\n", mxt->mxt_intr_gpio, i); - if (gpio_get_value(mxt->mxt_intr_gpio) == LOW) - break; - msleep(50); - } +static const struct attribute_group mxt_attr_group = { + .attrs = mxt_attrs, +}; - /* msleep(10000); */ +static void mxt_start(struct mxt_data *data) +{ + /* Touch enable */ + mxt_write_object(data, + MXT_TOUCH_MULTI, MXT_TOUCH_CTRL, 0x83); } -#endif -/* FIH } */ - - /* Get data that is defined in board specific code. */ - mxt->init_hw = pdata->init_platform_hw; - mxt->exit_hw = pdata->exit_platform_hw; - mxt->read_chg = pdata->read_chg; - if (pdata->valid_interrupt != NULL) - mxt->valid_interrupt = pdata->valid_interrupt; - else - mxt->valid_interrupt = mxt_valid_interrupt_dummy; +static void mxt_stop(struct mxt_data *data) +{ + /* Touch disable */ + mxt_write_object(data, + MXT_TOUCH_MULTI, MXT_TOUCH_CTRL, 0); +} - if (mxt->init_hw != NULL) - mxt->init_hw(); +static int mxt_input_open(struct input_dev *dev) +{ + struct mxt_data *data = input_get_drvdata(dev); - if (debug >= DEBUG_TRACE) - printk(KERN_INFO "maXTouch driver identifying chip\n"); + mxt_start(data); - if (mxt_identify(client, mxt, id_data) < 0) { - dev_err(&client->dev, "Chip could not be identified\n"); - error = -ENODEV; - goto err_identify; - } - /* Chip is valid and active. */ - if (debug >= DEBUG_TRACE) - printk(KERN_INFO "maXTouch driver allocating input device\n"); - - mxt->client = client; - mxt->touch_input = touch_input; - mxt->key_input = key_input; - - snprintf(mxt->touch_phys_name, sizeof(mxt->touch_phys_name), - "%s/input0", dev_name(&client->dev)); - snprintf(mxt->key_phys_name, sizeof(mxt->key_phys_name), - "%s/input1", dev_name(&client->dev)); - - /* Touch input parameter */ - touch_input->name = "mxt224_touchscreen_0"; - touch_input->phys = mxt->touch_phys_name; - touch_input->id.bustype = BUS_I2C; - touch_input->dev.parent = &client->dev; - - /* Key input parameter */ - key_input->name = "mxt224_key_0"; - key_input->phys = mxt->key_phys_name; - - /* Multitouch */ - input_set_abs_params(touch_input, ABS_MT_POSITION_X, TS_MIN_X, TS_MAX_X, 0, 0); - input_set_abs_params(touch_input, ABS_MT_POSITION_Y, TS_MIN_Y, TS_MAX_Y, 0, 0); - input_set_abs_params(touch_input, ABS_MT_TOUCH_MAJOR, 0, MXT_MAX_TOUCH_SIZE, - 0, 0); - input_set_abs_params(touch_input, ABS_MT_TRACKING_ID, 0, - MXT_MAX_NUM_TOUCHES, 0, 0); - - __set_bit(EV_ABS, touch_input->evbit); - __set_bit(EV_SYN, touch_input->evbit); - - /* Function key*/ - __set_bit(EV_KEY, key_input->evbit); - __set_bit(KEY_HOME, key_input->keybit); - __set_bit(KEY_MENU, key_input->keybit); - __set_bit(KEY_BACK, key_input->keybit); - __set_bit(KEY_SEARCH, key_input->keybit); - - i2c_set_clientdata(client, mxt); - input_set_drvdata(touch_input, mxt); - input_set_drvdata(key_input, mxt); - - error = input_register_device(mxt->touch_input); - if (error < 0) { - dev_err(&client->dev, "Failed to register touch input device\n"); - goto err_register_touch_device; - } + return 0; +} - error = input_register_device(mxt->key_input); - if (error < 0) { - dev_err(&client->dev, "Failed to register key input device in mxt224\n"); - goto err_register_key_device; - } +static void mxt_input_close(struct input_dev *dev) +{ + struct mxt_data *data = input_get_drvdata(dev); - mxt->message_buf = NULL; - error = mxt_read_object_table(client, mxt, id_data); - if (error < 0) - goto err_read_ot; - - BackupNVM(mxt); - msleep(40); - - mxt->prev_key = 0; - - if (pdata->numtouch) - mxt->numtouch = pdata->numtouch; - mxt->irq = gpio_to_irq(mxt->mxt_intr_gpio); - mxt->valid_irq_counter = 0; - mxt->invalid_irq_counter = 0; - mxt->irq_counter = 0; - - if (mxt->irq) { - error = request_threaded_irq(mxt->irq, NULL, - mxt_irq_handler, - IRQF_TRIGGER_FALLING, - client->dev.driver->name, - mxt); - if (error < 0) { - dev_err(&client->dev, - "failed to allocate irq %d\n", mxt->irq); - goto err_irq; - } - } + mxt_stop(data); +} - mutex_lock(&mxt->dev_mutex); - gpio_intr = gpio_get_value(mxt->mxt_intr_gpio); - while (gpio_intr == 0) { - for (i = 1; i < I2C_RETRY_COUNT; i++) { - error = mxt_read_block(mxt->client, mxt->msg_proc_addr, - mxt->message_size, mxt->message_buf); - if (error >= 0) - break; - dev_info(&client->dev, "flush the buffer failed in the probe function\n"); +static int __devinit mxt_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + const struct mxt_platform_data *pdata = client->dev.platform_data; + struct mxt_data *data; + struct input_dev *input_dev; + int error; - } - gpio_intr = gpio_get_value(mxt->mxt_intr_gpio); + if (!pdata) + return -EINVAL; - } - mutex_unlock(&mxt->dev_mutex); - - /* Store the number of multi-touches allowed, default was 0. */ - base_addr = get_object_address(MXT_TOUCH_MULTITOUCHSCREEN_T9, - 0, mxt->object_table, mxt->device_info.num_objs); - base_addr += MXT_ADR_T9_NUMTOUCH; - - error = mxt_write_byte(mxt->client, base_addr, mxt->numtouch); - if (error < 0) { - dev_err(&client->dev, - "Multi-touch init failure, T9 object, error = %d\n", - error); - goto err_irq; + data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!data || !input_dev) { + dev_err(&client->dev, "Failed to allocate memory\n"); + error = -ENOMEM; + goto err_free_mem; } - kfree(id_data); + input_dev->name = "Atmel maXTouch Touchscreen"; + input_dev->id.bustype = BUS_I2C; + input_dev->dev.parent = &client->dev; + input_dev->open = mxt_input_open; + input_dev->close = mxt_input_close; + + data->client = client; + data->input_dev = input_dev; + data->pdata = pdata; + data->irq = client->irq; + + mxt_calc_resolution(data); + + __set_bit(EV_ABS, input_dev->evbit); + __set_bit(EV_KEY, input_dev->evbit); + __set_bit(BTN_TOUCH, input_dev->keybit); + + /* For single touch */ + input_set_abs_params(input_dev, ABS_X, + 0, data->max_x, 0, 0); + input_set_abs_params(input_dev, ABS_Y, + 0, data->max_y, 0, 0); + + /* For multi touch */ + input_mt_init_slots(input_dev, MXT_MAX_FINGER); + input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, + 0, MXT_MAX_AREA, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_X, + 0, data->max_x, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, + 0, data->max_y, 0, 0); + + input_set_drvdata(input_dev, data); + i2c_set_clientdata(client, data); + + error = mxt_initialize(data); + if (error) + goto err_free_object; + + error = request_threaded_irq(client->irq, NULL, mxt_interrupt, + pdata->irqflags, client->dev.driver->name, data); + if (error) { + dev_err(&client->dev, "Failed to register interrupt\n"); + goto err_free_object; + } -#ifdef CONFIG_DEBUG_FS - error = intel_mid_add_debugfs(); - if (error < 0) - printk(KERN_ERR "failed to initialize intel_mid debugfs\n"); + error = mxt_make_highchg(data); + if (error) + goto err_free_irq; -#endif + error = input_register_device(input_dev); + if (error) + goto err_free_irq; -#ifdef CONFIG_HAS_EARLYSUSPEND - mxt->suspended = false; - mxt->T7[0] = 32; - mxt->T7[1] = 15; - mxt->T7[2] = 50; - mxt->es.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; - mxt->es.suspend = mxt_early_suspend; - mxt->es.resume = mxt_late_resume; - register_early_suspend(&mxt->es); - mxt_es = mxt; -#endif + error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group); + if (error) + goto err_unregister_device; return 0; -err_irq: - kfree(mxt->rid_map); - kfree(mxt->object_table); -err_read_ot: -err_register_key_device: -err_register_touch_device: -err_identify: -err_pdata: - input_free_device(key_input); -err_key_input_dev_alloc: - input_free_device(touch_input); -err_touch_input_dev_alloc: - kfree(id_data); -err_id_alloc: - if (mxt->exit_hw != NULL) - mxt->exit_hw(); - kfree(mxt); -err_mxt_alloc: +err_unregister_device: + input_unregister_device(input_dev); + input_dev = NULL; +err_free_irq: + free_irq(client->irq, data); +err_free_object: + kfree(data->object_table); +err_free_mem: + input_free_device(input_dev); + kfree(data); return error; } static int __devexit mxt_remove(struct i2c_client *client) { - struct mxt_data *mxt; - - mxt = i2c_get_clientdata(client); - - if (mxt != NULL) { - if (mxt->exit_hw != NULL) - mxt->exit_hw(); - - if (mxt->irq) - free_irq(mxt->irq, mxt); -#ifdef CONFIG_HAS_EARLYSUSPEND - unregister_early_suspend(&mxt->es); -#endif - input_unregister_device(mxt->key_input); - input_unregister_device(mxt->touch_input); - kfree(mxt->rid_map); - kfree(mxt->object_table); - kfree(mxt->message_buf); - } - kfree(mxt); + struct mxt_data *data = i2c_get_clientdata(client); - if (debug >= DEBUG_TRACE) - dev_info(&client->dev, "Touchscreen unregistered\n"); + sysfs_remove_group(&client->dev.kobj, &mxt_attr_group); + free_irq(data->irq, data); + input_unregister_device(data->input_dev); + kfree(data->object_table); + kfree(data); return 0; } -#if defined(CONFIG_PM) +#ifdef CONFIG_PM static int mxt_suspend(struct device *dev) { - struct mxt_data *mxt = dev_get_drvdata(dev); - - dev_dbg(dev, "In function %s", __func__); - - if (device_may_wakeup(dev)) - enable_irq_wake(mxt->irq); - - return 0; -} + struct i2c_client *client = to_i2c_client(dev); + struct mxt_data *data = i2c_get_clientdata(client); + struct input_dev *input_dev = data->input_dev; -static int mxt_resume(struct device *dev) -{ - struct mxt_data *mxt = dev_get_drvdata(dev); + mutex_lock(&input_dev->mutex); - dev_dbg(dev, "In function %s", __func__); + if (input_dev->users) + mxt_stop(data); - if (device_may_wakeup(dev)) - disable_irq_wake(mxt->irq); + mutex_unlock(&input_dev->mutex); return 0; } -#else -#define mxt_suspend NULL -#define mxt_resume NULL -#endif -#ifdef CONFIG_HAS_EARLYSUSPEND -void mxt_early_suspend(struct early_suspend *h) +static int mxt_resume(struct device *dev) { - u16 pwcfg_addr; - u8 buf[3] = {0, 0, 0}; - u8 err; + struct i2c_client *client = to_i2c_client(dev); + struct mxt_data *data = i2c_get_clientdata(client); + struct input_dev *input_dev = data->input_dev; - disable_irq(mxt_es->irq); + /* Soft reset */ + mxt_write_object(data, MXT_GEN_COMMAND, + MXT_COMMAND_RESET, 1); - mutex_lock(&mxt_es->dev_mutex); + msleep(MXT_RESET_TIME); + mutex_lock(&input_dev->mutex); - pwcfg_addr = get_object_address(MXT_GEN_POWERCONFIG_T7, - 0, mxt_es->object_table, - mxt_es->device_info.num_objs); - mxt_read_block(mxt_es->client, pwcfg_addr, 3, mxt_es->T7); - err = mxt_write_block(mxt_es->client, pwcfg_addr, 3, buf); - if (err > 0) - dev_info(&mxt_es->client->dev, "Driver enter deep sleep mode."); - else - dev_info(&mxt_es->client->dev, - "Driver can't enter deep sleep mode [%d].", err); - /* clear touch state when suspending */ - memset(stored_size, 0, mxt_es->numtouch * sizeof(stored_size[0])); - report_mt(mxt_es); + if (input_dev->users) + mxt_start(data); - mxt_es->suspended = true; + mutex_unlock(&input_dev->mutex); - mutex_unlock(&mxt_es->dev_mutex); + return 0; } -void mxt_late_resume(struct early_suspend *h) -{ - int gpio_intr; - u16 pwcfg_addr; - u8 err; - u8 i; - - enable_irq(mxt_es->irq); - mutex_lock(&mxt_es->dev_mutex); - - pwcfg_addr = get_object_address(MXT_GEN_POWERCONFIG_T7, - 0, - mxt_es->object_table, - mxt_es->device_info.num_objs); -/* FIH { */ -#if 0 - err = mxt_write_block(mxt_es->client, pwcfg_addr, 3, mxt_es->T7); -#else - for (i = 0; i < I2C_RETRY_COUNT; i++) { - err = mxt_write_block(mxt_es->client, pwcfg_addr, 3, mxt_es->T7); - if (err == 3) - break; - msleep(100); - } -#endif -/* FIH } */ - if (err > 0) - dev_info(&mxt_es->client->dev, "resume from early suspend"); - else - dev_info(&mxt_es->client->dev, "fail to late resume"); - - msleep(25); - gpio_intr = gpio_get_value(mxt_es->mxt_intr_gpio); - while (gpio_intr == 0) { - for (i = 1; i < I2C_RETRY_COUNT; i++) { - err = mxt_read_block(mxt_es->client, - mxt_es->msg_proc_addr, - mxt_es->message_size, - mxt_es->message_buf); - if (err >= 0) - break; - dev_info(&mxt_es->client->dev, "flush the buffer failed in the resume function\n"); - - } - gpio_intr = gpio_get_value(mxt_es->mxt_intr_gpio); - - } - mxt_calibrate(mxt_es->client); - mxt_es->suspended = false; - mutex_unlock(&mxt_es->dev_mutex); - -} -#endif - static const struct dev_pm_ops mxt_pm_ops = { - .suspend = mxt_suspend, - .resume = mxt_resume, + .suspend = mxt_suspend, + .resume = mxt_resume, }; +#endif -static const struct i2c_device_id mxt_idtable[] = { - {TOUCH_DEVICE_NAME, 1,}, +static const struct i2c_device_id mxt_id[] = { + { "qt602240_ts", 0 }, + { "atmel_mxt_ts", 0 }, + { "mXT224", 0 }, { } }; - -MODULE_DEVICE_TABLE(i2c, mxt_idtable); +MODULE_DEVICE_TABLE(i2c, mxt_id); static struct i2c_driver mxt_driver = { .driver = { - .name = TOUCH_DEVICE_NAME, - .owner = THIS_MODULE, + .name = "atmel_mxt_ts", + .owner = THIS_MODULE, #ifdef CONFIG_PM - .pm = &mxt_pm_ops, + .pm = &mxt_pm_ops, #endif }, - - .id_table = mxt_idtable, .probe = mxt_probe, .remove = __devexit_p(mxt_remove), + .id_table = mxt_id, }; static int __init mxt_init(void) { - int err; - - err = i2c_add_driver(&mxt_driver); - if (err) { - printk(KERN_WARNING "Adding maXTouch driver(Here for mxt224) failed " - "(errno = %d)\n", err); - } else { - printk(KERN_INFO "Successfully added driver %s\n", - mxt_driver.driver.name); - } - return err; + return i2c_add_driver(&mxt_driver); } -static void __exit mxt_cleanup(void) +static void __exit mxt_exit(void) { i2c_del_driver(&mxt_driver); } +module_init(mxt_init); +module_exit(mxt_exit); -late_initcall(mxt_init); -module_exit(mxt_cleanup); - -MODULE_AUTHOR("Iiro Valkonen"); -MODULE_DESCRIPTION("Driver for Atmel maXTouch Touchscreen Controller"); +/* Module information */ +MODULE_AUTHOR("Joonyoung Shim "); +MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver"); MODULE_LICENSE("GPL"); - - -#ifdef CONFIG_DEBUG_FS -/****************************************************************************** -debugfs for touch driver, contain four debug files: - -1.sread - can be read and write. - write: set the address of a single register to be accessed; - read: return the content of the register. -2.swrite - can be write only. - write: set the value of the corresponding register, and the register's - address is determined by 'write' operation of 'single_read' file. -3.sread_offset - can be write only - write:set the offset of the register -*********************************************************************************/ - - -static int intel_mid_single_read_get(void *data, u64 *val) -{ - int ret, gpio_intr, gpio_rst; - u16 addr; - addr = get_object_address(reg_add, - 0, - mxt_es->object_table, - mxt_es->device_info.num_objs)+reg_add_offset; - - ret = mxt_read_block(mxt_es->client, addr, 1, (u8 *)val); - if (ret < 0) - printk(KERN_ERR "intel_touch debugfs read_set err add=0x%x\n", reg_add); - gpio_intr = gpio_get_value(mxt_es->mxt_intr_gpio); - gpio_rst = gpio_get_value(mxt_es->mxt_reset_gpio); - printk("touch interrupt value = %d,gpio_rst = %d\n", gpio_intr, gpio_rst); - return 0; -} - -static int intel_mid_single_read_set(void *data, u64 val) -{ - reg_add = (u8)val; - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(intel_mid_single_read_reg_fops, - intel_mid_single_read_get, - intel_mid_single_read_set, "0x%02llx\n"); - -static int intel_mid_single_read_set_offset(void *data, u64 val) -{ - reg_add_offset = (u8)val; - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(intel_mid_single_read_reg_offset_fops, - NULL, intel_mid_single_read_set_offset, - "0x%02llx\n"); - -static int intel_mid_single_write_set(void *data, u64 val) -{ - int ret; - u16 addr; - uint8_t data1[1] = {0}; - data1[0] = (u8)val; - addr = get_object_address(reg_add, - 0, - mxt_es->object_table, - mxt_es->device_info.num_objs)+reg_add_offset; - - ret = mxt_write_block(mxt_es->client, addr, 1, data1); - - if (ret < 0) - printk(KERN_ERR "intel_touch debugfs write err add=0x%x\n", reg_add); - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(intel_mid_single_write_reg_fops, - NULL, intel_mid_single_write_set, "0x%02llx\n"); - - -static int intel_mid_add_debugfs(void) -{ - struct dentry *root; - - root = debugfs_create_dir("touch_debug", NULL); - - if (IS_ERR(root)) - /* Don't complain -- debugfs just isn't enabled */ - return -1; - if (!root) - /* Complain -- debugfs is enabled, but it failed to - * create the directory. */ - goto err; - - if (!debugfs_create_file("sread", S_IWUGO|S_IRUGO, root, NULL, &intel_mid_single_read_reg_fops)) - goto err; - - if (!debugfs_create_file ("sread_offset", S_IWUGO|S_IRUGO, root, NULL, &intel_mid_single_read_reg_offset_fops)) - goto err; - - if (!debugfs_create_file ("swrite", S_IWUGO, root, NULL, &intel_mid_single_write_reg_fops)) - goto err; - - return 0; -err: - debugfs_remove_recursive(root); - printk(KERN_ERR "failed to initialize intel_mid debugfs\n"); - return -1; -} - -#endif diff --git a/include/linux/atmel_mxt_ts.h b/include/linux/atmel_mxt_ts.h deleted file mode 100644 index c5253a8..0000000 --- a/include/linux/atmel_mxt_ts.h +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Atmel maXTouch header file - * - * Copyright (c) 2010 Atmel Corporation - * Copyright (C) 2010 Ulf Samuelsson (ulf@atmel.com) - * Contains changes by Wind River Systems, 2010-09-29 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * See the file "COPYING" in the main directory of this archive - * for more details. - * - * Modified by Richard Zhu(jianxin.zhu@borqs.com) 05/19/2011 - */ -#include - -#define MXT224_I2C_ADDR1 0x4A -#define MXT224_I2C_ADDR2 0x4B -#define MXT1386_I2C_ADDR1 0x4C -#define MXT1386_I2C_ADDR2 0x4D -#define MXT1386_I2C_ADDR3 0x5A -#define MXT1386_I2C_ADDR4 0x5B - -/* - * Select this address from above depending on what maXTouch - * chip you have and how it's address pins are configured; - * see datasheet. - */ - -#define MXT_I2C_ADDRESS MXT1386_I2C_ADDR1 - -#define MXT_BL_ADDRESS 0x25 - -#define MXT224_FAMILYID 0x80 -#define MXT1386_FAMILYID 0xA0 - -#define MXT224_CAL_VARIANTID 0x01 -#define MXT224_UNCAL_VARIANTID 0x00 -#define MXT1386_CAL_VARIANTID 0x00 - -#define MXT_MAX_REPORTED_WIDTH 255 -#define MXT_MAX_REPORTED_PRESSURE 255 -#define MXT_MAX_TOUCH_SIZE 255 -#define MXT_MAX_NUM_TOUCHES 10 - -/* Fixed addresses inside maXTouch device */ -#define MXT_ADDR_INFO_BLOCK 0 -#define MXT_ADDR_OBJECT_TABLE 7 -#define MXT_ID_BLOCK_SIZE 7 -#define MXT_OBJECT_TABLE_ELEMENT_SIZE 6 - -/* Object types */ -#define MXT_DEBUG_DELTAS_T2 2 -#define MXT_DEBUG_REFERENCES_T3 3 -#define MXT_GEN_MESSAGEPROCESSOR_T5 5 -#define MXT_GEN_COMMANDPROCESSOR_T6 6 -#define MXT_GEN_POWERCONFIG_T7 7 -#define MXT_GEN_ACQUIRECONFIG_T8 8 -#define MXT_TOUCH_MULTITOUCHSCREEN_T9 9 -#define MXT_TOUCH_SINGLETOUCHSCREEN_T10 10 -#define MXT_TOUCH_XSLIDER_T11 11 -#define MXT_TOUCH_YSLIDER_T12 12 -#define MXT_TOUCH_XWHEEL_T13 13 -#define MXT_TOUCH_YWHEEL_T14 14 -#define MXT_TOUCH_KEYARRAY_T15 15 -#define MXT_SPT_COMMSCONFIG_T18 18 -#define MXT_SPT_GPIOPWM_T19 19 -#define MXT_PROCI_GRIPFACESUPPRESSION_T20 20 -#define MXT_PROCG_NOISESUPPRESSION_T22 22 -#define MXT_TOUCH_PROXIMITY_T23 23 -#define MXT_PROCI_ONETOUCHGESTUREPROCESSOR_T24 24 -#define MXT_SPT_SELFTEST_T25 25 -#define MXT_DEBUG_CTERANGE_T26 26 -#define MXT_PROCI_TWOTOUCHGESTUREPROCESSOR_T27 27 -#define MXT_SPT_CTECONFIG_T28 28 -#define MXT_TOUCH_KEYSET_T31 31 -#define MXT_TOUCH_XSLIDERSET_T32 32 -#define MXT_DEBUG_DIAGNOSTIC_T37 37 -#define MXT_USER_INFO_T38 38 -#define MXT_PROCI_GRIPSUPPRESSION_T40 40 -#define MXT_PROCI_PALMSUPPRESSION_T41 41 -#define MXT_SPT_DIGITIZER_T43 43 - - -/* - * If a message is read from mXT when there's no new messages available, - * the report ID of the message will be 0xFF. - */ -#define MXT_END_OF_MESSAGES 0xFF - - -/* GEN_COMMANDPROCESSOR_T6 Register offsets from T6 base address */ -#define MXT_ADR_T6_RESET 0x00 -#define MXT_ADR_T6_BACKUPNV 0x01 -#define MXT_ADR_T6_CALIBRATE 0x02 -#define MXT_ADR_T6_REPORTALL 0x03 -#define MXT_ADR_T6_RESERVED 0x04 -#define MXT_ADR_T6_DIAGNOSTIC 0x05 - -/* T6 Debug Diagnostics Commands */ -#define MXT_CMD_T6_PAGE_UP 0x01 -#define MXT_CMD_T6_PAGE_DOWN 0x02 -#define MXT_CMD_T6_DELTAS_MODE 0x10 -#define MXT_CMD_T6_REFERENCES_MODE 0x11 -#define MXT_CMD_T6_CTE_MODE 0x31 - -/* T6 Backup Command */ -#define MXT_CMD_T6_BACKUP 0x55 - -/* SPT_DEBUG_DIAGNOSTIC_T37 Register offsets from T37 base address */ -#define MXT_ADR_T37_PAGE 0x01 -#define MXT_ADR_T37_DATA 0x02 - - - -/************************************************************************ - * MESSAGE OBJECTS ADDRESS FIELDS - * - ************************************************************************/ -#define MXT_MSG_REPORTID 0x00 - - -/* MXT_GEN_MESSAGEPROCESSOR_T5 Message address definitions */ -#define MXT_MSG_T5_REPORTID 0x00 -#define MXT_MSG_T5_MESSAGE 0x01 -#define MXT_MSG_T5_CHECKSUM 0x08 - -/* MXT_GEN_COMMANDPROCESSOR_T6 Message address definitions */ -#define MXT_MSG_T6_STATUS 0x01 -#define MXT_MSGB_T6_COMSERR 0x04 -#define MXT_MSGB_T6_CFGERR 0x08 -#define MXT_MSGB_T6_CAL 0x10 -#define MXT_MSGB_T6_SIGERR 0x20 -#define MXT_MSGB_T6_OFL 0x40 -#define MXT_MSGB_T6_RESET 0x80 -/* Three bytes */ -#define MXT_MSG_T6_CHECKSUM 0x02 - -/* MXT_GEN_POWERCONFIG_T7 NO Message address definitions */ -/* MXT_GEN_ACQUIRECONFIG_T8 Message address definitions */ -/* MXT_TOUCH_MULTITOUCHSCREEN_T9 Message address definitions */ - -#define T8_CFG_CHRGTIME 0 -/* Reserved */ -#define T8_CFG_TCHDRIFT 2 -#define T8_CFG_DRIFTST 3 -#define T8_CFG_TCHAUTOCAL 4 -#define T8_CFG_SYNC 5 -#define T8_CFG_ATCHCALST 6 -#define T8_CFG_ATCHCALSTHR 7 -#define T8_CFG_ATCHFRCCALTHR 8 /* FW v2.x */ -#define T8_CFG_ATCHFRCCALRATIO 9 /* FW v2.x */ - -#define MXT_MSG_T9_STATUS 0x01 -/* Status bit field */ -#define MXT_MSGB_T9_SUPPRESS 0x02 -#define MXT_MSGB_T9_AMP 0x04 -#define MXT_MSGB_T9_VECTOR 0x08 -#define MXT_MSGB_T9_MOVE 0x10 -#define MXT_MSGB_T9_RELEASE 0x20 -#define MXT_MSGB_T9_PRESS 0x40 -#define MXT_MSGB_T9_DETECT 0x80 - -#define MXT_MSG_T9_XPOSMSB 0x02 -#define MXT_MSG_T9_YPOSMSB 0x03 -#define MXT_MSG_T9_XYPOSLSB 0x04 -#define MXT_MSG_T9_TCHAREA 0x05 -#define MXT_MSG_T9_TCHAMPLITUDE 0x06 -#define MXT_MSG_T9_TCHVECTOR 0x07 -#define MXT_MSG_T9_ORIENT 0x09 -/* ORIENT field settings. */ -#define MXT_MSGB_T9_ORIENT_NORMAL_ORIENT 0X00 -#define MXT_MSGB_T9_ORIENT_HORZ_FLIP 0x02 -#define MXT_MSGB_T9_ORIENT_VERT_FLIP 0x04 -#define MXT_MSGB_T9_ORIENT_ROTATE_180 0x06 -#define MXT_MSGB_T9_ORIENT_DIAG_X0_Y0_XMAX_YMAX 0x01 -#define MXT_MSGB_T9_ORIENT_ROTATE_90_CCWISE 0x03 -#define MXT_MSGB_T9_ORIENT_ROTATE_90_CWISE 0x05 -#define MXT_MSGB_T9_ORIENT_DIAG_X0_YMAX_XMAX_Y0 0x07 - -#define MXT_ADR_T9_NUMTOUCH 0x0e - -/* MXT_SPT_GPIOPWM_T19 Message address definitions */ -#define MXT_MSG_T19_STATUS 0x01 - -/* MXT_PROCI_GRIPFACESUPPRESSION_T20 Message address definitions */ -#define MXT_MSG_T20_STATUS 0x01 -#define MXT_MSGB_T20_FACE_SUPPRESS 0x01 -/* MXT_PROCG_NOISESUPPRESSION_T22 Message address definitions */ -#define MXT_MSG_T22_STATUS 0x01 -#define MXT_MSGB_T22_FHCHG 0x01 -#define MXT_MSGB_T22_GCAFERR 0x04 -#define MXT_MSGB_T22_FHERR 0x08 -#define MXT_MSG_T22_GCAFDEPTH 0x02 - -/* MXT_TOUCH_PROXIMITY_T23 Message address definitions */ -#define MXT_MSG_T23_STATUS 0x01 -#define MXT_MSGB_T23_FALL 0x20 -#define MXT_MSGB_T23_RISE 0x40 -#define MXT_MSGB_T23_DETECT 0x80 -/* 16 bit */ -#define MXT_MSG_T23_PROXDELTA 0x02 - -/* MXT_PROCI_ONETOUCHGESTUREPROCESSOR_T24 Message address definitions */ -#define MXT_MSG_T24_STATUS 0x01 -#define MXT_MSG_T24_XPOSMSB 0x02 -#define MXT_MSG_T24_YPOSMSB 0x03 -#define MXT_MSG_T24_XYPOSLSB 0x04 -#define MXT_MSG_T24_DIR 0x05 -/* 16 bit */ -#define MXT_MSG_T24_DIST 0x06 - -/* MXT_SPT_SELFTEST_T25 Message address definitions */ -#define MXT_ADR_T25_CTRL 0x00 -#define MXT_MSG_T25_STATUS 0x01 -#define MXT_ADR_T25_CMD 0x01 - -/* 5 Bytes */ -#define MXT_MSGR_T25_INVALID_TEST 0xFD -#define MXT_MSGR_T25_PIN_FAULT 0x11 -#define MXT_MSGR_T25_SIGNAL_LIMIT_FAULT 0x17 -#define MXT_MSGR_T25_GAIN_ERROR 0x20 -#define MXT_MSGR_T25_RUN_ALL_TESTS 0xFE -#define MXT_MSG_T25_INFO 0x02 - -/* MXT_PROCI_TWOTOUCHGESTUREPROCESSOR_T27 Message address definitions */ -#define MXT_MSG_T27_STATUS 0x01 -#define MXT_MSGB_T27_ROTATEDIR 0x10 -#define MXT_MSGB_T27_PINCH 0x20 -#define MXT_MSGB_T27_ROTATE 0x40 -#define MXT_MSGB_T27_STRETCH 0x80 -#define MXT_MSG_T27_XPOSMSB 0x02 -#define MXT_MSG_T27_YPOSMSB 0x03 -#define MXT_MSG_T27_XYPOSLSB 0x04 -#define MXT_MSG_T27_ANGLE 0x05 - -/* 16 bit */ -#define MXT_MSG_T27_SEPARATION 0x06 - -/* MXT_SPT_CTECONFIG_T28 Message address definitions */ -#define MXT_MSG_T28_STATUS 0x01 -#define MXT_MSGB_T28_CHKERR 0x01 - - -/* One Touch Events */ -#define MXT_GESTURE_RESERVED 0x00 -#define MXT_GESTURE_PRESS 0x01 -#define MXT_GESTURE_RELEASE 0x02 -#define MXT_GESTURE_TAP 0x03 -#define MXT_GESTURE_DOUBLE_TAP 0x04 -#define MXT_GESTURE_FLICK 0x05 -#define MXT_GESTURE_DRAG 0x06 -#define MXT_GESTURE_SHORT_PRESS 0x07 -#define MXT_GESTURE_LONG_PRESS 0x08 -#define MXT_GESTURE_REPEAT_PRESS 0x09 -#define MXT_GESTURE_TAP_AND_PRESS 0x0a -#define MXT_GESTURE_THROW 0x0b - -/* Two-touch events */ -#define MXT_GESTURE_STRETCH (1 << 7) -#define MXT_GESTURE_ROTATE (1 << 6) -#define MXT_GESTURE_PINCH (1 << 5) -#define MXT_GESTURE_ROTATEDIR (1 << 4) - - - -/* Bootloader states */ -#define WAITING_BOOTLOAD_COMMAND 0xC0 -#define WAITING_FRAME_DATA 0x80 -#define APP_CRC_FAIL 0x40 -#define FRAME_CRC_CHECK 0x02 -#define FRAME_CRC_PASS 0x04 -#define FRAME_CRC_FAIL 0x03 - -#define MXT_MAX_FRAME_SIZE 276 - -/* Debug levels */ -#define DEBUG_INFO 1 -#define DEBUG_VERBOSE 2 -#define DEBUG_MESSAGES 5 -#define DEBUG_RAW 8 -#define DEBUG_TRACE 10 - -/* IOCTL commands */ -/* TODO: get correct numbers! */ -#define MXT_IOC_MAGIC 'x' - -/* Sets the internal address pointer */ -#define MXT_SET_ADDRESS_IOCTL _IO(MXT_IOC_MAGIC, 1) -/* Resets the device */ -#define MXT_RESET_IOCTL _IO(MXT_IOC_MAGIC, 2) -/* Calibrates the device */ -#define MXT_CALIBRATE_IOCTL _IO(MXT_IOC_MAGIC, 3) -/* Backups the current state of registers to NVM */ -#define MXT_BACKUP_IOCTL _IO(MXT_IOC_MAGIC, 4) -/* Only non-touch messages can be read from the message buffer - * (/dev/maXTouch_messages)*/ -#define MXT_NONTOUCH_MSG_IOCTL _IO(MXT_IOC_MAGIC, 5) -/* All messages can be read from the message buffer */ -#define MXT_ALL_MSG_IOCTL _IO(MXT_IOC_MAGIC, 6) -/* self test */ -#define MXT_SELF_TEST_IOCTL _IO(MXT_IOC_MAGIC, 7) - -/* Message buffer size. This is a ring buffer, and when full, the oldest entry - will be overwritten. */ -#define MXT_MESSAGE_BUFFER_SIZE 128 - -/* TODO: */ -/* Bootloader specific function prototypes. */ -#if 0 -static int mxt_read_byte_bl(struct i2c_client *client, u8 *value); -static int mxt_read_block_bl(struct i2c_client *client, u16 length, u8 *value); -static int mxt_write_byte_bl(struct i2c_client *client, u8 value); -static int mxt_write_block_bl(struct i2c_client *client, u16 length, u8 *value); -#endif - -/** - * struct mxt_platform_data - includes platform specific information - * related to Atmel maXTouch touchscreen controller. - * - * @numtouch: Number of simultaneous touches supported - * @init_platform_hw(): Initialization function, which can for example - * trigger a hardware reset by toggling a GPIO pin - * @exit_platform_hw(): Function to run when the driver is unloaded. - * @valid_interrupt(): Function that checks the validity of the interrupt - - * function that check the validity of a interrupt (by - * reading the changeline interrupt pin and checking that - * it really is low for example). - * @max_x: Reported X range - * @max_y: Reported Y range - */ - -struct mxt_platform_data { - u8 numtouch; /* Number of touches to report */ - void (*init_platform_hw)(void); - void (*exit_platform_hw)(void); - int max_x; /* The default reported X range */ - int max_y; /* The default reported Y range */ - int orientation; /* The default orientation */ - u8 (*valid_interrupt) (void); - u8 (*read_chg) (void); - u16 reset; - u16 irq; -}; - -void mxt_hw_reset(void); - -/* Add by Richard zhu(jianxin.zhu@borqs.com) */ -#define TOUCH_DEVICE_NAME "mxt1386" -#define LOW 0 -#define HIGH 1 -#define FALSE 0 -#define TRUE 1 -#define TS_MAX_X 1023 -#define TS_MIN_X 0 -#define TS_MAX_Y 1023 -#define TS_MIN_Y 0 - -/* anti-touch calibration */ -#define RECALIB_NEED 0 -#define RECALIB_NG 1 -#define RECALIB_DONE 2 - -struct point_info { - int x; - int y; - int num; - int first_area; - int last_area; -}; - -enum touch_state { - NO_TOUCH = 0, - PRESS_TOUCH_AREA, -}; -- 2.7.4