/* * atmel_maxtouch.c - Atmel maXTouch Touchscreen Controller * * Version 0.2a * * An early alpha version of the maXTouch Linux driver. * * * Copyright (C) 2010 Iiro Valkonen * Copyright (C) 2009 Ulf Samuelsson * Copyright (C) 2009 Raphael Derosso Pereira * * 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. * * 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. */ #define DEBUG_INFO 1 #define DEBUG_VERBOSE 2 #define DEBUG_MESSAGES 5 #define DEBUG_RAW 8 #define DEBUG_TRACE 10 #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 #include #include #include "atmel_mxt1386_cfg.h" #include #include #ifdef CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK #include #include #define SEC_DVFS_LOCK_TIMEOUT 3 #endif /* * This is a driver for the Atmel maXTouch Object Protocol * * When the driver is loaded, mxt_init is called. * mxt_driver registers the "mxt_driver" structure in the i2c subsystem * The mxt_idtable.name string allows the board support to associate * the driver with its own data. * * The i2c subsystem will call the mxt_driver.probe == mxt_probe * to detect the device. * mxt_probe will reset the maXTouch device, and then * determine the capabilities of the I2C peripheral in the * host processor (needs to support BYTE transfers) * * If OK; mxt_probe will try to identify which maXTouch device it is * by calling mxt_identify. * * If a known device is found, a linux input device is initialized * the "mxt" device data structure is allocated * as well as an input device structure "mxt->input" * "mxt->client" is provided as a parameter to mxt_probe. * * mxt_read_object_table is called to determine which objects * are present in the device, and to determine their adresses * * * Addressing an object: * * The object is located at a 16 address in the object address space * * The object address can vary between revisions of the firmware * * The address is provided through an object descriptor table in the beginning * of the object address space. * It is assumed that an object type is only listed once in this table, * Each object type can have several instances, and the number of * instances is available in the object table * * The base address of the first instance of an object is stored in * "mxt->object_table[object_type].chip_addr", * This is indexed by the object type and allows direct access to the * first instance of an object. * * Each instance of an object is assigned a "Report Id" uniquely identifying * this instance. Information about this instance is available in the * "mxt->report_id" variable, which is a table indexed by the "Report Id". * * The maXTouch object protocol supports adding a checksum to messages. * By setting the most significant bit of the maXTouch address * an 8 bit checksum is added to all writes. * * * How to use driver. * ----------------- * Example: * In arch/avr32/boards/atstk1000/atstk1002.c * an "i2c_board_info" descriptor is declared. * This contains info about which driver ("mXT224"), * which i2c address and which pin for CHG interrupts are used. * * In the "atstk1002_init" routine, "i2c_register_board_info" is invoked * with this information. Also, the I/O pins are configured, and the I2C * controller registered is on the application processor. * */ #if 1/*for debugging, enable DEBUG_TRACE*/ static int debug = DEBUG_INFO; #else static int debug = DEBUG_TRACE; /* for debugging*/ #endif /* #define ITDEV */ #ifdef ITDEV static int driver_paused; static int debug_enabled; #endif #define MXT_MESSAGE_LENGTH 8 #ifdef CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK static void free_dvfs_lock(struct work_struct *work) { struct mxt_data *mxt = container_of(work, struct mxt_data, dvfs_dwork.work); exynos4_busfreq_lock_free(DVFS_LOCK_ID_TSP); exynos_cpufreq_lock_free(DVFS_LOCK_ID_TSP); mxt->dvfs_lock_status = false; } static void set_dvfs_lock(struct mxt_data *mxt, bool on) { if (0 == mxt->cpufreq_level) exynos_cpufreq_get_level(800000, &mxt->cpufreq_level); if (on) { cancel_delayed_work(&mxt->dvfs_dwork); if (!mxt->dvfs_lock_status) { exynos4_busfreq_lock(DVFS_LOCK_ID_TSP, BUS_L1); exynos_cpufreq_lock(DVFS_LOCK_ID_TSP, mxt->cpufreq_level); mxt->dvfs_lock_status = true; } } else { if (mxt->dvfs_lock_status) schedule_delayed_work(&mxt->dvfs_dwork, SEC_DVFS_LOCK_TIMEOUT * HZ); } } #endif module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Activate debugging output"); #define I2C_RETRY_COUNT 5 /* Returns the start address of object in mXT memory. */ #define MXT_BASE_ADDR(object_type) \ get_object_address(object_type, 0, mxt->object_table, mxt->device_info.num_objs) /* If report_id (rid) == 0, then "mxt->report_id[rid].object" will be 0. */ #define REPORT_ID_TO_OBJECT(rid) \ (((rid) == 0xff) ? 0 : mxt->rid_map[rid].object) #define REPORT_ID_TO_OBJECT_NAME(rid) \ object_type_name[REPORT_ID_TO_OBJECT(rid)] #define T6_REG(x) (MXT_BASE_ADDR(MXT_GEN_COMMANDPROCESSOR_T6) + (x)) #define T37_REG(x) (MXT_BASE_ADDR(MXT_DEBUG_DIAGNOSTICS_T37) + (x)) #define REPORT_MT(x, y, amplitude, size) \ do { \ input_report_abs(mxt->input, ABS_MT_POSITION_X, x); \ input_report_abs(mxt->input, ABS_MT_POSITION_Y, y); \ input_report_abs(mxt->input, ABS_MT_TOUCH_MAJOR, amplitude); \ input_report_abs(mxt->input, ABS_MT_WIDTH_MAJOR, size); \ } while (0) const u8 *maxtouch_family = "maXTouch"; const u8 *mxt224_variant = "mXT1386"; u8 *object_type_name[MXT_MAX_OBJECT_TYPES] = { /* [0] = "Reserved", */ /* [2] = "T2 - Obsolete", */ /* [3] = "T3 - Obsolete", */ [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] = "T19 - Obsolete",*/ [22] = "PROCG_NOISESUPPRESSION_T22", /* [23] = "T23 - Obsolete",*/ [24] = "PROCI_ONETOUCHGESTUREPROCESSOR_T24", [25] = "SPT_SELFTEST_T25", /* [26] = "T26 - Obsolete",*/ [27] = "PROCI_TWOTOUCHGESTUREPROCESSOR_T27", [28] = "SPT_CTECONFIG_T28", [37] = "DEBUG_DIAGNOSTICS_T37", [38] = "USER_DATA_T38", [40] = "PROCI_GRIPSUPPRESSION_T40", [41] = "PROCI_PALMSUPPRESSION_T41", [43] = "SPT_DIGITIZER_T43", [44] = "SPT_MESSAGECOUNT_T44", }; int backup_to_nv(struct mxt_data *mxt) { /* backs up settings to the non-volatile memory */ return mxt_write_byte(mxt->client, MXT_BASE_ADDR(MXT_GEN_COMMANDPROCESSOR_T6) + MXT_ADR_T6_BACKUPNV, 0x55); } int reset_chip(struct mxt_data *mxt, u8 mode) { u8 data; printk(KERN_DEBUG "[TSP] Reset chip Reset mode (%d)", mode); if (mode == RESET_TO_NORMAL) data = 0x1;/* non-zero value*/ else if (mode == RESET_TO_BOOTLOADER) data = 0xA5; else { pr_err("Invalid reset mode(%d)", mode); return -1; } /* Any non-zero value written to reset reg will reset the chip */ return mxt_write_byte(mxt->client, MXT_BASE_ADDR(MXT_GEN_COMMANDPROCESSOR_T6) + MXT_ADR_T6_RESET, data); } #ifdef MXT_ERROR_WORKAROUND static void mxt_forced_release(struct mxt_data *mxt) { int i; printk(KERN_DEBUG "[TSP] %s has been called", __func__); for (i = 0; i < MXT_MAX_NUM_TOUCHES; ++i) { input_mt_slot(mxt->input, i); input_mt_report_slot_state(mxt->input, MT_TOOL_FINGER, 0); mxt->mtouch_info[i].status = TSP_STATE_INACTIVE; } input_sync(mxt->input); #ifdef CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK set_dvfs_lock(mxt, false); #endif } static void mxt_force_reset(struct mxt_data *mxt) { if (mxt->pdata->suspend_platform_hw && mxt->pdata->resume_platform_hw) { mxt->pdata->suspend_platform_hw(); msleep(400); mxt->pdata->resume_platform_hw(); } mxt_forced_release(mxt); } #endif /*mode 1 = Charger connected */ /*mode 0 = Charger disconnected*/ static void mxt_inform_charger_connection(struct mxt_callbacks *cb, int mode) { struct mxt_data *mxt = container_of(cb, struct mxt_data, callbacks); mxt->set_mode_for_ta = !!mode; if (mxt->enabled && !work_pending(&mxt->ta_work)) schedule_work(&mxt->ta_work); } static void mxt_ta_worker(struct work_struct *work) { struct mxt_data *mxt = container_of(work, struct mxt_data, ta_work); static u8 blen; static u8 tchthr; static u8 noisethr; static u8 idlegcafdepth; static u8 movefilter; static u8 idleacqint; static u8 freqscale; static u8 jumplimit; int i = 0; u8 fhe_cnt = 0; u8 freq[5]; u16 setting_bit = 0; printk(KERN_DEBUG "[TSP] TA/USB is%sconnected.\n", mxt->set_mode_for_ta ? " " : " dis"); if (0 == mxt->pdata->fherr_cnt) { tchthr = mxt->pdata->touchscreen_config.tchthr; noisethr = mxt->pdata->noise_suppression_config.noisethr; idlegcafdepth = mxt->pdata->cte_config.idlegcafdepth; idleacqint = mxt->pdata->power_config.idleacqint; movefilter = mxt->pdata->touchscreen_config.movfilter; blen = mxt->pdata->touchscreen_config.blen; jumplimit = mxt->pdata->touchscreen_config.jumplimit; freqscale = mxt->pdata->noise_suppression_config.freqhopscale; if (!mxt->set_mode_for_ta) return ; } for (i = 0; i < 5; i++) freq[i] = mxt->pdata->noise_suppression_config.freq[i]; if (mxt->set_mode_for_ta) { if (mxt->pdata->fherr_cnt >= mxt->pdata->fherr_chg_cnt) { blen = mxt->pdata->tch_blen_for_fherr; SET_BIT(setting_bit, TSP_SETTING_BLEN); tchthr = mxt->pdata->tchthr_for_fherr; SET_BIT(setting_bit, TSP_SETTING_TCHTHR); noisethr = mxt->pdata->noisethr_for_fherr; SET_BIT(setting_bit, TSP_SETTING_NOISETHR); movefilter = mxt->pdata->movefilter_for_fherr; SET_BIT(setting_bit, TSP_SETTING_MOVEFILTER); if (jumplimit != mxt->pdata->jumplimit_for_fherr) { jumplimit = mxt->pdata->jumplimit_for_fherr; SET_BIT(setting_bit, TSP_SETTING_JUMPLIMIT); } if (freqscale != mxt->pdata->freqhopscale_for_fherr) { freqscale = mxt->pdata->freqhopscale_for_fherr; SET_BIT(setting_bit, TSP_SETTING_FREQ_SCALE); } fhe_cnt = (mxt->pdata->fherr_cnt / mxt->pdata->fherr_chg_cnt) % 4; SET_BIT(setting_bit, TSP_SETTING_FREQUENCY); for (i = 0; i < 5; i++) { switch (fhe_cnt) { case 1: freq[i] = mxt->pdata->freq_for_fherr1[i]; break; case 2: freq[i] = mxt->pdata->freq_for_fherr2[i]; break; case 3: freq[i] = mxt->pdata->freq_for_fherr3[i]; break; case 0: default: break; } } } else { tchthr = mxt->pdata->tchthr_for_ta_connect; SET_BIT(setting_bit, TSP_SETTING_TCHTHR); noisethr = mxt->pdata->noisethr_for_ta_connect; SET_BIT(setting_bit, TSP_SETTING_NOISETHR); if (idlegcafdepth != mxt->pdata->idlegcafdepth_ta_connect) { idlegcafdepth = mxt->pdata->idlegcafdepth_ta_connect; SET_BIT(setting_bit, TSP_SETTING_IDLEDEPTH); } if (idleacqint != mxt->pdata->idleacqint_for_ta_connect) { idleacqint = mxt->pdata->idleacqint_for_ta_connect; SET_BIT(setting_bit, TSP_SETTING_IDLEACQINT); } } } else { mxt->pdata->fherr_cnt = 0; tchthr = mxt->pdata->touchscreen_config.tchthr; SET_BIT(setting_bit, TSP_SETTING_TCHTHR); noisethr = mxt->pdata->noise_suppression_config. noisethr; SET_BIT(setting_bit, TSP_SETTING_NOISETHR); movefilter = mxt->pdata->touchscreen_config.movfilter; SET_BIT(setting_bit, TSP_SETTING_MOVEFILTER); blen = mxt->pdata->touchscreen_config.blen; SET_BIT(setting_bit, TSP_SETTING_BLEN); if (idlegcafdepth != mxt->pdata->cte_config.idlegcafdepth) { idlegcafdepth = mxt->pdata->cte_config.idlegcafdepth; SET_BIT(setting_bit, TSP_SETTING_IDLEDEPTH); } if (idleacqint != mxt->pdata->power_config.idleacqint) { idleacqint = mxt->pdata->power_config.idleacqint; SET_BIT(setting_bit, TSP_SETTING_IDLEACQINT); } if (jumplimit != mxt->pdata->touchscreen_config.jumplimit) { jumplimit = mxt->pdata->touchscreen_config.jumplimit; SET_BIT(setting_bit, TSP_SETTING_JUMPLIMIT); } if (freqscale != mxt->pdata->noise_suppression_config. freqhopscale) { freqscale = mxt->pdata->noise_suppression_config. freqhopscale; SET_BIT(setting_bit, TSP_SETTING_FREQ_SCALE); } } printk(KERN_DEBUG "[TSP] setting_bit : %x\n", setting_bit); for (i = 0; i < 5; i++) printk(KERN_DEBUG "[TSP] frequency[%d] : %u\n", i, freq[i]); disable_irq(mxt->client->irq); if (setting_bit & (0x1 << TSP_SETTING_BLEN)) mxt_write_byte(mxt->client, MXT_BASE_ADDR(MXT_TOUCH_MULTITOUCHSCREEN_T9) + MXT_ADR_T9_BLEN, blen); /* change to ta_connect config*/ /* tchthr change*/ if (setting_bit & (0x1 << TSP_SETTING_TCHTHR)) mxt_write_byte(mxt->client, MXT_BASE_ADDR(MXT_TOUCH_MULTITOUCHSCREEN_T9) + MXT_ADR_T9_TCHTHR, tchthr); /* noisethr change*/ if (setting_bit & (0x1 << TSP_SETTING_NOISETHR)) mxt_write_byte(mxt->client, MXT_BASE_ADDR(MXT_PROCG_NOISESUPPRESSION_T22) + MXT_ADR_T22_NOISETHR, noisethr); /* freq change*/ if (setting_bit & (0x1 << TSP_SETTING_FREQUENCY)) { mxt_write_block(mxt->client, MXT_BASE_ADDR(MXT_PROCG_NOISESUPPRESSION_T22) + MXT_ADR_T22_FREQ, 5, freq); printk(KERN_DEBUG "[TSP] frequency table chage : %u\n", mxt->pdata->fherr_cnt); } /* frequency scale */ if (setting_bit & (0x1 << TSP_SETTING_FREQ_SCALE)) mxt_write_byte(mxt->client, MXT_BASE_ADDR(MXT_PROCG_NOISESUPPRESSION_T22) + MXT_ADR_T22_FREQHOPSCALE, freqscale); /* idlegcafdepth change*/ if (setting_bit & (0x1 << TSP_SETTING_IDLEDEPTH)) mxt_write_byte(mxt->client, MXT_BASE_ADDR(MXT_SPT_CTECONFIG_T28) + MXT_ADR_T28_IDLEGCAFDEPTH, idlegcafdepth); /* idleacqint change*/ if (setting_bit & (0x1 << TSP_SETTING_IDLEACQINT)) mxt_write_byte(mxt->client, MXT_BASE_ADDR(MXT_GEN_POWERCONFIG_T7) + MXT_ADR_T7_IDLEACQINT, idleacqint); /* move filter change */ if (setting_bit & (0x1 << TSP_SETTING_MOVEFILTER)) mxt_write_byte(mxt->client, MXT_BASE_ADDR(MXT_TOUCH_MULTITOUCHSCREEN_T9) + MXT_ADR_T9_MOVFILTER, movefilter); /* move filter change */ if (setting_bit & (0x1 << TSP_SETTING_JUMPLIMIT)) mxt_write_byte(mxt->client, MXT_BASE_ADDR(MXT_TOUCH_MULTITOUCHSCREEN_T9) + 30, jumplimit); #if 0 /* mxt_calibrate : non-zero value*/ mxt_write_byte(mxt->client, MXT_BASE_ADDR(MXT_GEN_COMMANDPROCESSOR_T6) + MXT_ADR_T6_CALIBRATE, 0x1); #endif enable_irq(mxt->client->irq); } static void mxt_fhe_worker(struct work_struct *work) { struct mxt_data *mxt = container_of(work, struct mxt_data, fhe_work); printk(KERN_DEBUG "[TSP] fherr_no_ta : %u\n", mxt->pdata->fherr_cnt_no_ta); if (mxt->pdata->fherr_cnt_no_ta == mxt->pdata->fherr_chg_cnt_no_ta) { int ret = 0; disable_irq(mxt->client->irq); /* blen */ ret = mxt_write_byte(mxt->client, MXT_BASE_ADDR(MXT_TOUCH_MULTITOUCHSCREEN_T9) + MXT_ADR_T9_BLEN, mxt->pdata->tch_blen_for_fherr_no_ta); printk(KERN_DEBUG "[TSP] tch_blen_for_fherr_no_ta : %u - (%d)\n", mxt->pdata->tch_blen_for_fherr_no_ta, ret); /* tchthr change*/ ret = mxt_write_byte(mxt->client, MXT_BASE_ADDR(MXT_TOUCH_MULTITOUCHSCREEN_T9) + MXT_ADR_T9_TCHTHR, mxt->pdata->tchthr_for_fherr_no_ta); printk(KERN_DEBUG "[TSP] tchthr_for_fherr_no_ta : %u - (%d)\n", mxt->pdata->tchthr_for_fherr_no_ta, ret); /* move filter change */ ret = mxt_write_byte(mxt->client, MXT_BASE_ADDR(MXT_TOUCH_MULTITOUCHSCREEN_T9) + MXT_ADR_T9_MOVFILTER, mxt->pdata->movfilter_fherr_no_ta); printk(KERN_DEBUG "[TSP] movfilter_fherr_no_ta : %u - (%d)\n", mxt->pdata->movfilter_fherr_no_ta, ret); /* noisethr change*/ ret = mxt_write_byte(mxt->client, MXT_BASE_ADDR(MXT_PROCG_NOISESUPPRESSION_T22) + MXT_ADR_T22_NOISETHR, mxt->pdata->noisethr_for_fherr_no_ta); printk(KERN_DEBUG "[TSP] noisethr_for_fherr_no_ta : %u - (%d)\n", mxt->pdata->noisethr_for_fherr_no_ta, ret); enable_irq(mxt->client->irq); } else if (mxt->pdata->fherr_cnt_no_ta % 5) mxt->fherr_cnt_no_ta_calready = 1; } #ifdef MXT_CALIBRATE_WORKAROUND static void mxt_calibrate_worker(struct work_struct *work) { struct mxt_data *mxt; u8 buf[4]; int error; mxt = container_of(work, struct mxt_data, calibrate_dwork.work); if (mxt->enabled == true) { disable_irq(mxt->client->irq); memcpy(buf, &mxt->pdata->atchcalst_idle, sizeof(buf)); printk(KERN_DEBUG "[TSP] %s\n", __func__); /* change auto calibration config*/ /* from atchcalst to atchcalfrcratio change*/ error = mxt_write_block(mxt->client, MXT_BASE_ADDR(MXT_GEN_ACQUIRECONFIG_T8) + MXT_ADR_T8_ATCHCALST, 4, (u8 *) buf); if (error < 0) pr_err("[TSP] error %s: write_object : from atchcalst to atchcalfrcratio\n", __func__); enable_irq(mxt->client->irq); } } #endif /* Calculates the 24-bit CRC sum. */ static u32 mxt_CRC_24(u32 crc, u8 byte1, u8 byte2) { static const u32 crcpoly = 0x80001B; u32 result; u16 data_word; data_word = (u16) ((u16) (byte2 << 8u) | byte1); result = ((crc << 1u) ^ (u32) data_word); if (result & 0x1000000) result ^= crcpoly; return result; } /* Returns object address in mXT chip, or zero if object is not found */ u16 get_object_address(uint8_t object_type, uint8_t instance, struct mxt_object *object_table, int max_objs) { 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 return 0; } object_table_index++; } return address; } /* Returns object size in mXT chip, or zero if object is not found */ u16 get_object_size(uint8_t object_type, struct mxt_object *object_table, int max_objs) { uint8_t object_table_index = 0; struct mxt_object obj; while (object_table_index < max_objs) { obj = object_table[object_table_index]; if (obj.type == object_type) return obj.size; object_table_index++; } return 0; } /* * Reads one byte from given address from mXT chip (which requires * writing the 16-bit address pointer first). */ int mxt_read_byte(struct i2c_client *client, u16 addr, u8 *value) { struct i2c_adapter *adapter = client->adapter; struct i2c_msg msg[2]; __le16 le_addr = cpu_to_le16(addr); struct mxt_data *mxt; mxt = i2c_get_clientdata(client); 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 = 1; msg[1].buf = (u8 *) value; if (i2c_transfer(adapter, msg, 2) == 2) { mxt->last_read_addr = addr; return 0; } else { /* * In case the transfer failed, set last read addr to invalid * address, so that the next reads won't get confused. */ mxt->last_read_addr = -1; return -EIO; } } /* * 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) { struct i2c_adapter *adapter = client->adapter; struct i2c_msg msg[2]; __le16 le_addr; struct mxt_data *mxt; mxt = i2c_get_clientdata(client); if (mxt != NULL) { if ((mxt->last_read_addr == addr) && (addr == mxt->msg_proc_addr)) { if (i2c_master_recv(client, value, length) == length) { #ifdef ITDEV if (debug_enabled) print_hex_dump(KERN_DEBUG, "MXT RX:", DUMP_PREFIX_NONE, 16, 1, value, length, false); #endif return 0; } else return -EIO; } else { mxt->last_read_addr = addr; } } 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; if (i2c_transfer(adapter, msg, 2) == 2) { #ifdef ITDEV if (debug_enabled) { print_hex_dump(KERN_DEBUG, "MXT TX:", DUMP_PREFIX_NONE, 16, 1, msg[0].buf, msg[0].len, false); print_hex_dump(KERN_DEBUG, "MXT RX:", DUMP_PREFIX_NONE, 16, 1, msg[1].buf, msg[1].len, false); } #endif return 0; } else return -EIO; } /* Reads a block of bytes from current address from mXT chip. */ static int mxt_read_block_wo_addr(struct i2c_client *client, u16 length, u8 *value) { if (i2c_master_recv(client, value, length) == length) { printk(KERN_DEBUG "read ok\n"); #ifdef ITDEV if (debug_enabled) print_hex_dump(KERN_DEBUG, "MXT RX:", DUMP_PREFIX_NONE, 16, 1, value, length, false); #endif return length; } else { printk(KERN_DEBUG "read failed\n"); return -EIO; } } /* Writes one byte to given address in mXT chip. */ int mxt_write_byte(struct i2c_client *client, u16 addr, u8 value) { struct { __le16 le_addr; u8 data; } i2c_byte_transfer; struct mxt_data *mxt; 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) { #ifdef ITDEV if (debug_enabled) print_hex_dump(KERN_DEBUG, "MXT TX:", DUMP_PREFIX_NONE, 16, 1, &i2c_byte_transfer, 3, false); #endif return 0; } else return -EIO; } /* Writes a block of bytes (max 256) to given address in mXT chip. */ int mxt_write_block(struct i2c_client *client, u16 addr, u16 length, u8 *value) { int i; struct { __le16 le_addr; u8 data[256]; } i2c_block_transfer; struct mxt_data *mxt; if (length > 256) return -EINVAL; mxt = i2c_get_clientdata(client); if (mxt != NULL) mxt->last_read_addr = -1; for (i = 0; i < length; i++) i2c_block_transfer.data[i] = *value++; i2c_block_transfer.le_addr = cpu_to_le16(addr); i = i2c_master_send(client, (u8 *) &i2c_block_transfer, length + 2); if (i == (length + 2)) { #ifdef ITDEV if (debug_enabled) print_hex_dump(KERN_DEBUG, "MXT TX:", DUMP_PREFIX_NONE, 16, 1, &i2c_block_transfer, length+2, false); #endif return length; } else return -EIO; } /* TODO: make all other access block until the read has been done? Otherwise an arriving message for example could set the ap to message window, and then the read would be done from wrong address! */ /* Writes the address pointer (to set up following reads). */ static int mxt_write_ap(struct i2c_client *client, u16 ap) { __le16 le_ap = cpu_to_le16(ap); struct mxt_data *mxt; mxt = i2c_get_clientdata(client); if (mxt != NULL) mxt->last_read_addr = -1; printk(KERN_DEBUG "Address pointer set to %d\n", ap); if (i2c_master_send(client, (u8 *) &le_ap, 2) == 2) { #ifdef ITDEV if (debug_enabled) print_hex_dump(KERN_DEBUG, "MXT TX:", DUMP_PREFIX_NONE, 16, 1, &le_ap, 2, false); #endif return 0; } else return -EIO; } /* Calculates the CRC value for mXT infoblock. */ static int calculate_infoblock_crc(struct mxt_data *mxt, u32 *crc_result) { u32 crc = 0; u16 crc_area_size; u8 *mem; int i; int error; struct i2c_client *client; client = mxt->client; crc_area_size = MXT_ID_BLOCK_SIZE + mxt->device_info.num_objs * MXT_OBJECT_TABLE_ELEMENT_SIZE; mem = kmalloc(crc_area_size, GFP_KERNEL); if (mem == NULL) { dev_err(&client->dev, "Error allocating memory\n"); return -ENOMEM; } error = mxt_read_block(client, 0, crc_area_size, mem); if (error < 0) { kfree(mem); return error; } for (i = 0; i < (crc_area_size - 1); i = i + 2) crc = mxt_CRC_24(crc, *(mem + i), *(mem + i + 1)); /* If uneven size, pad with zero */ if (crc_area_size & 0x0001) crc = mxt_CRC_24(crc, *(mem + i), 0); kfree(mem); /* Return only 24 bits of CRC. */ *crc_result = (crc & 0x00FFFFFF); return 1; } #ifdef ITDEV /* Functions for mem_access interface */ struct bin_attribute mem_access_attr; static ssize_t mem_access_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { int ret = 0; struct i2c_client *client; printk(KERN_DEBUG "mem_access_read p=%p off=%lli c=%zi\n", buf, off, count); if (off >= 32768) return -EIO; if (off + count > 32768) count = 32768 - off; if (count > 256) count = 256; if (count > 0) { client = to_i2c_client(container_of(kobj, struct device, kobj)); ret = mxt_read_block(client, off, count, buf); } return ret >= 0 ? count : ret; } static ssize_t mem_access_write(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { int ret = 0; struct i2c_client *client; printk(KERN_DEBUG "mem_access_write p=%p off=%lli c=%zi\n", buf, off, count); if (off >= 32768) return -EIO; if (off + count > 32768) count = 32768 - off; if (count > 256) count = 256; if (count > 0) { client = to_i2c_client(container_of(kobj, struct device, kobj)); ret = mxt_write_block(client, off, count, buf); } return ret >= 0 ? count : 0; } #endif static void process_T9_message(struct mxt_data *mxt, u8 *message) { struct input_dev *input; u8 status; u8 report_id; u8 touch_id; /* to identify each touches. starts from 0 to 15*/ u8 pressed_or_released = 0; u8 anytouch_pressed = 0; u16 xpos = 0xFFFF; u16 ypos = 0xFFFF; static int prev_touch_id = -1; #ifdef CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK bool tsp_boost = false; #endif input = mxt->input; status = message[MXT_MSG_T9_STATUS]; report_id = message[0]; touch_id = report_id - 2; if (touch_id >= MXT_MAX_NUM_TOUCHES) { pr_err("[TSP] Invalid touch_id (toud_id=%d)", touch_id); return; } /* Put together the 10-/12-bit coordinate values. */ 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); if (mxt->pdata->max_x < 1024) xpos >>= 2; if (mxt->pdata->max_y < 1024) ypos >>= 2; mxt->mtouch_info[touch_id].size = message[MXT_MSG_T9_TCHAREA]; if (status & MXT_MSGB_T9_DETECT) { /* case 1: detected */ /* touch amplitude */ mxt->mtouch_info[touch_id].pressure = message[MXT_MSG_T9_TCHAMPLITUDE]; mxt->mtouch_info[touch_id].x = (int16_t)xpos; mxt->mtouch_info[touch_id].y = (int16_t)ypos; pressed_or_released = 1; if (status & MXT_MSGB_T9_PRESS) { mxt->mtouch_info[touch_id].status = TSP_STATE_PRESS; printk(KERN_DEBUG "mxt %d p\n", touch_id); } } else if (status & MXT_MSGB_T9_RELEASE) { /* case 2: released */ pressed_or_released = 1; mxt->mtouch_info[touch_id].status = TSP_STATE_RELEASE; mxt->mtouch_info[touch_id].pressure = 0; printk(KERN_DEBUG "mxt %d r\n", touch_id); } else if (status & MXT_MSGB_T9_SUPPRESS) { /* case 3: suppressed */ /* * Atmel's recommendation: * In the case of supression, * mxt1386 chip doesn't make a release event. * So we need to release them forcibly. */ mxt_forced_release(mxt); } else pr_err("[TSP] Unknown status (0x%x)", status); if (pressed_or_released) { input_mt_slot(mxt->input, touch_id); input_mt_report_slot_state(mxt->input, MT_TOOL_FINGER, !!mxt->mtouch_info[touch_id].pressure); if (TSP_STATE_RELEASE == mxt->mtouch_info[touch_id].status) mxt->mtouch_info[touch_id].status = TSP_STATE_INACTIVE; else { REPORT_MT( mxt->mtouch_info[touch_id].x, mxt->mtouch_info[touch_id].y, mxt->mtouch_info[touch_id].pressure, mxt->mtouch_info[touch_id].size); #ifdef CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK tsp_boost = true; anytouch_pressed++; #endif } if (mxt->fherr_cnt_no_ta_calready && (!anytouch_pressed)) { mxt->fherr_cnt_no_ta_calready = 0; /* mxt_calibrate : non-zero value*/ mxt_write_byte(mxt->client, MXT_BASE_ADDR(MXT_GEN_COMMANDPROCESSOR_T6) + MXT_ADR_T6_CALIBRATE, 0x1); } input_sync(input); #ifdef CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK set_dvfs_lock(mxt, tsp_boost); #endif } prev_touch_id = touch_id; if (debug >= DEBUG_TRACE) { char msg[64] = {0}; char info[64] = {0}; if (status & MXT_MSGB_T9_SUPPRESS) { strcpy(msg, "Suppress: "); } else { if (status & MXT_MSGB_T9_DETECT) { strcpy(msg, "Detect("); if (status & MXT_MSGB_T9_PRESS) strcat(msg, "P"); if (status & MXT_MSGB_T9_MOVE) strcat(msg, "M"); if (status & MXT_MSGB_T9_AMP) strcat(msg, "A"); if (status & MXT_MSGB_T9_VECTOR) strcat(msg, "V"); strcat(msg, "): "); } else if (status & MXT_MSGB_T9_RELEASE) { strcpy(msg, "Release: "); } else { strcpy(msg, "[!] Unknown status: "); } } sprintf(info, "(%d,%d) amp=%d, size=%d", xpos, ypos, message[MXT_MSG_T9_TCHAMPLITUDE], message[MXT_MSG_T9_TCHAREA]); strcat(msg, info); printk(KERN_DEBUG "%s\n", msg); } return; } int process_message(struct mxt_data *mxt, u8 *message, u8 object) { struct i2c_client *client; u8 status; u16 xpos = 0xFFFF; u16 ypos = 0xFFFF; u8 event; u8 length; u8 report_id; 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) printk(KERN_ERR "[TSP] maXTouch checksum error\n"); if (status & MXT_MSGB_T6_CFGERR) printk(KERN_ERR "[TSP] maXTouch configuration error\n"); if (status & MXT_MSGB_T6_CAL) printk(KERN_DEBUG "[TSP] maXTouch calibration in progress\n"); if (status & MXT_MSGB_T6_SIGERR) { printk(KERN_ERR "[TSP] maXTouch acquisition error\n"); #ifdef MXT_ERROR_WORKAROUND mxt_force_reset(mxt); #endif } if (status & MXT_MSGB_T6_OFL) { printk(KERN_ERR "[TSP] maXTouch cycle overflow\n"); #ifdef MXT_ERROR_WORKAROUND /* soft reset */ /*typical atmel spec. value is 250ms, but it sometimes fails to recover so it needs more*/ reset_chip(mxt, RESET_TO_NORMAL); msleep(300); #endif } if (status & MXT_MSGB_T6_RESET) printk(KERN_DEBUG "[TSP] maXTouch chip reset\n"); if (status == 0) { printk(KERN_DEBUG "[TSP] maXTouch status normal\n"); #if defined(MXT_FACTORY_TEST) /*check if firmware started*/ if (mxt->firm_status_data == 1) { printk(KERN_DEBUG "[TSP] maXTouch mxt->firm_normal_status_ack after firm up\n"); /*got normal status ack*/ mxt->firm_normal_status_ack = 1; } #endif } break; case MXT_TOUCH_MULTITOUCHSCREEN_T9: #ifdef ITDEV if (!driver_paused) #endif process_T9_message(mxt, message); break; case MXT_PROCG_NOISESUPPRESSION_T22: if (debug >= DEBUG_TRACE) printk(KERN_DEBUG "[TSP] Receiving noise suppression msg\n"); status = message[MXT_MSG_T22_STATUS]; if (status & MXT_MSGB_T22_FHCHG) { if (debug >= DEBUG_TRACE) printk(KERN_DEBUG "[TSP] maXTouch: Freq changed\n"); } if (status & MXT_MSGB_T22_GCAFERR) { if (debug >= DEBUG_TRACE) printk(KERN_DEBUG "[TSP] maXTouch: High noise " "level\n"); } if (status & MXT_MSGB_T22_FHERR) { mxt->pdata->fherr_cnt++; printk(KERN_DEBUG "[TSP] frequency hopping err : %u\n", mxt->pdata->fherr_cnt); if (mxt->set_mode_for_ta) { printk(KERN_DEBUG "[TSP] fherr : %u\n", ++mxt->pdata->fherr_cnt); if (0 == (mxt->pdata->fherr_cnt % mxt->pdata->fherr_chg_cnt)) if (!work_pending(&mxt->ta_work)) schedule_work(&mxt->ta_work); } else { mxt->pdata->fherr_cnt_no_ta++; if (!work_pending(&mxt->fhe_work)) schedule_work(&mxt->fhe_work); } } break; case MXT_PROCI_ONETOUCHGESTUREPROCESSOR_T24: if (debug >= DEBUG_TRACE) printk(KERN_DEBUG "[TSP] 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; switch (event) { case MT_GESTURE_RESERVED: break; case MT_GESTURE_PRESS: break; case MT_GESTURE_RELEASE: break; case MT_GESTURE_TAP: break; case MT_GESTURE_DOUBLE_TAP: break; case MT_GESTURE_FLICK: break; case MT_GESTURE_DRAG: break; case MT_GESTURE_SHORT_PRESS: break; case MT_GESTURE_LONG_PRESS: break; case MT_GESTURE_REPEAT_PRESS: break; case MT_GESTURE_TAP_AND_PRESS: break; case MT_GESTURE_THROW: break; default: break; } break; case MXT_SPT_SELFTEST_T25: if (debug >= DEBUG_TRACE) printk(KERN_DEBUG "[TSP] Receiving Self-Test msg\n"); if (message[MXT_MSG_T25_STATUS] == MXT_MSGR_T25_OK) { if (debug >= DEBUG_TRACE) printk(KERN_DEBUG "[TSP] maXTouch: Self-Test OK\n"); } else { printk(KERN_DEBUG "[TSP] 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; case MXT_PROCI_TWOTOUCHGESTUREPROCESSOR_T27: if (debug >= DEBUG_TRACE) printk(KERN_DEBUG "[TSP] Receiving 2-touch gesture message\n"); break; case MXT_SPT_CTECONFIG_T28: if (debug >= DEBUG_TRACE) printk(KERN_DEBUG "[TSP] Receiving CTE message...\n"); status = message[MXT_MSG_T28_STATUS]; if (status & MXT_MSGB_T28_CHKERR) printk(KERN_DEBUG "[TSP] maXTouch: Power-Up CRC failure\n"); break; default: if (debug >= DEBUG_TRACE) dev_info(&client->dev, "maXTouch: Unknown message!\n"); break; } return 0; } /* Processes messages when the interrupt line (CHG) is asserted. */ static void mxt_threaded_irq_handler(struct mxt_data *mxt) { struct i2c_client *client; /*note: changed message_length to 8 in ver0.9*/ u8 message[MXT_MESSAGE_LENGTH]; u16 message_length; u16 message_addr; u8 report_id; u8 object; int error; int i; client = mxt->client; message_addr = mxt->msg_proc_addr; message_length = mxt->message_size; if (debug >= DEBUG_TRACE) dev_info(&mxt->client->dev, "maXTouch worker active:\n"); /* Read next message */ mxt->message_counter++; mxt->read_fail_counter = 0; /* Reread on failure! */ for (i = 1; i < I2C_RETRY_COUNT; i++) { /*note: changed message_length to 8 in ver0.9*/ error = mxt_read_block(client, message_addr, MXT_MESSAGE_LENGTH, message); if (error >= 0) break; mxt->read_fail_counter++; /* Register read failed */ printk(KERN_DEBUG "[TSP] Failure reading maxTouch device\n"); } #ifdef MXT_ERROR_WORKAROUND /*reset mxt touch ic if the i2c error occurs continuously*/ if (mxt->read_fail_counter == I2C_RETRY_COUNT - 1) { mxt_force_reset(mxt); mxt->read_fail_counter = 0; return; } #endif report_id = message[0]; if (debug >= DEBUG_RAW) { printk(KERN_DEBUG "%s message [%08x]:", REPORT_ID_TO_OBJECT_NAME(report_id), mxt->message_counter ); for (i = 0; i < message_length; i++) printk(KERN_DEBUG "0x%02x ", message[i]); printk(KERN_DEBUG "\n"); } #ifdef ITDEV if (debug_enabled) print_hex_dump(KERN_DEBUG, "MXT MSG:", DUMP_PREFIX_NONE, 16, 1, message, message_length, false); #endif if ((report_id != MXT_END_OF_MESSAGES) && (report_id != 0)) { for (i = 0; i < message_length; i++) mxt->last_message[i] = message[i]; #if 0 if (down_interruptible(&mxt->msg_sem)) { printk(KERN_DEBUG "mxt_worker Interrupted " "while waiting for msg_sem!\n"); return; } #endif mxt->new_msgs = 1; #if 0 up(&mxt->msg_sem); #endif wake_up_interruptible(&mxt->msg_queue); /* Get type of object and process the message */ object = mxt->rid_map[report_id].object; process_message(mxt, message, object); } } static irqreturn_t mxt_threaded_irq(int irq, void *_mxt) { struct mxt_data *mxt = _mxt; /* mxt->irq_counter++; printk(KERN_DEBUG "mxt_threaded_irq : irq_counter = %d", mxt->irq_counter); */ mxt_threaded_irq_handler(mxt); return IRQ_HANDLED; } /* Function to write a block of data to any address on touch chip. */ #define I2C_PAYLOAD_SIZE 254 static ssize_t set_config(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int i; u16 address; int whole_blocks; int last_block_size; struct i2c_client *client = to_i2c_client(dev); address = *((u16 *) buf); address = cpu_to_be16(address); buf += 2; whole_blocks = (count - 2) / I2C_PAYLOAD_SIZE; last_block_size = (count - 2) % I2C_PAYLOAD_SIZE; for (i = 0; i < whole_blocks; i++) { mxt_write_block(client, address, I2C_PAYLOAD_SIZE, (u8 *) buf); address += I2C_PAYLOAD_SIZE; buf += I2C_PAYLOAD_SIZE; } mxt_write_block(client, address, last_block_size, (u8 *) buf); return count; } static ssize_t get_config(struct device *dev, struct device_attribute *attr, char *buf) { int i; struct i2c_client *client = to_i2c_client(dev); struct mxt_data *mxt = i2c_get_clientdata(client); printk(KERN_DEBUG "Reading %d bytes from current ap\n", mxt->bytes_to_read); if (0 == mxt->bytes_to_read) return 0; i = mxt_read_block_wo_addr(client, mxt->bytes_to_read, (u8 *) buf); return (ssize_t) i; } /* * Sets up a read from mXT chip. If we want to read config data from user space * we need to use this first to tell the address and byte count, then use * get_config to read the data. */ static ssize_t set_ap(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int i; struct i2c_client *client; struct mxt_data *mxt; u16 ap; client = to_i2c_client(dev); mxt = i2c_get_clientdata(client); if (count < 3) { /* Error, ap needs to be two bytes, plus 1 for size! */ printk(KERN_DEBUG "set_ap needs to arguments: address pointer " "and data size"); return -EIO; } ap = (u16) *((u16 *)buf); i = mxt_write_ap(client, ap); mxt->bytes_to_read = (u16) *(buf + 2); return count; } static ssize_t show_deltas(struct device *dev, struct device_attribute *attr, char *buf) { struct i2c_client *client; struct mxt_data *mxt; s16 *delta; s16 size, read_size; u16 diagnostics; u16 debug_diagnostics; char *bufp; int x, y; int error; u16 *val; client = to_i2c_client(dev); mxt = i2c_get_clientdata(client); /* Allocate buffer for delta's */ size = mxt->device_info.num_nodes * sizeof(__u16); if (mxt->delta == NULL) { mxt->delta = kzalloc(size, GFP_KERNEL); if (!mxt->delta) { sprintf(buf, "insufficient memory\n"); return strlen(buf); } } if (mxt->object_table[MXT_GEN_COMMANDPROCESSOR_T6].type == 0) { dev_err(&client->dev, "maXTouch: Object T6 not found\n"); return 0; } diagnostics = T6_REG(MXT_ADR_T6_DIAGNOSTICS); if (mxt->object_table[MXT_DEBUG_DIAGNOSTICS_T37].type == 0) { dev_err(&client->dev, "maXTouch: Object T37 not found\n"); return 0; } debug_diagnostics = T37_REG(2); /* Configure T37 to show deltas */ error = mxt_write_byte(client, diagnostics, MXT_CMD_T6_DELTAS_MODE); if (error) return error; delta = mxt->delta; while (size > 0) { read_size = size > 128 ? 128 : size; error = mxt_read_block(client, debug_diagnostics, read_size, (__u8 *) delta); if (error < 0) { mxt->read_fail_counter++; dev_err(&client->dev, "maXTouch: Error reading delta object\n"); } delta += (read_size / 2); size -= read_size; /* Select next page */ mxt_write_byte(client, diagnostics, MXT_CMD_T6_PAGE_UP); } bufp = buf; val = (s16 *) mxt->delta; for (x = 0; x < mxt->device_info.x_size; x++) { for (y = 0; y < mxt->device_info.y_size; y++) bufp += sprintf(bufp, "%05d ", (s16) le16_to_cpu(*val++)); bufp -= 2; /* No spaces at the end */ bufp += sprintf(bufp, "\n"); } bufp += sprintf(bufp, "\n"); return strlen(buf); } static ssize_t show_references(struct device *dev, struct device_attribute *attr, char *buf) { struct i2c_client *client; struct mxt_data *mxt; s16 *reference; s16 size, read_size; u16 diagnostics; u16 debug_diagnostics; char *bufp; int x, y; int error; u16 *val; client = to_i2c_client(dev); mxt = i2c_get_clientdata(client); /* Allocate buffer for reference's */ size = mxt->device_info.num_nodes * sizeof(u16); if (mxt->reference == NULL) { mxt->reference = kzalloc(size, GFP_KERNEL); if (!mxt->reference) { sprintf(buf, "insufficient memory\n"); return strlen(buf); } } if (mxt->object_table[MXT_GEN_COMMANDPROCESSOR_T6].type == 0) { dev_err(&client->dev, "maXTouch: Object T6 not found\n"); return 0; } diagnostics = T6_REG(MXT_ADR_T6_DIAGNOSTICS); if (mxt->object_table[MXT_DEBUG_DIAGNOSTICS_T37].type == 0) { dev_err(&client->dev, "maXTouch: Object T37 not found\n"); return 0; } debug_diagnostics = T37_REG(2); /* Configure T37 to show references */ mxt_write_byte(client, diagnostics, MXT_CMD_T6_REFERENCES_MODE); /* Should check for error */ reference = mxt->reference; while (size > 0) { read_size = size > 128 ? 128 : size; error = mxt_read_block(client, debug_diagnostics, read_size, (__u8 *) reference); if (error < 0) { mxt->read_fail_counter++; dev_err(&client->dev, "maXTouch: Error reading reference object\n"); } reference += (read_size / 2); size -= read_size; /* Select next page */ mxt_write_byte(client, diagnostics, MXT_CMD_T6_PAGE_UP); } bufp = buf; val = (u16 *) mxt->reference; for (x = 0; x < mxt->device_info.x_size; x++) { for (y = 0; y < mxt->device_info.y_size; y++) bufp += sprintf(bufp, "%05d ", le16_to_cpu(*val++)); bufp -= 2; /* No spaces at the end */ bufp += sprintf(bufp, "\n"); } bufp += sprintf(bufp, "\n"); return strlen(buf); } static ssize_t show_device_info(struct device *dev, struct device_attribute *attr, char *buf) { struct i2c_client *client; struct mxt_data *mxt; char *bufp; client = to_i2c_client(dev); mxt = i2c_get_clientdata(client); bufp = buf; bufp += sprintf(bufp, "Family:\t\t\t[0x%02x] %s\n", mxt->device_info.family_id, mxt->device_info.family ); bufp += sprintf(bufp, "Variant:\t\t[0x%02x] %s\n", mxt->device_info.variant_id, mxt->device_info.variant ); bufp += sprintf(bufp, "Firmware version:\t[%d.%d], build 0x%02X\n", mxt->device_info.major, mxt->device_info.minor, mxt->device_info.build ); bufp += sprintf(bufp, "%d Sensor nodes:\t[X=%d, Y=%d]\n", mxt->device_info.num_nodes, mxt->device_info.x_size, mxt->device_info.y_size ); bufp += sprintf(bufp, "Reported resolution:\t[X=%d, Y=%d]\n", mxt->pdata->max_x+1, mxt->pdata->max_y+1 ); return strlen(buf); } static ssize_t show_stat(struct device *dev, struct device_attribute *attr, char *buf) { struct i2c_client *client; struct mxt_data *mxt; char *bufp; client = to_i2c_client(dev); mxt = i2c_get_clientdata(client); bufp = buf; bufp += sprintf(bufp, "Interrupts:\t[VALID=%d ; INVALID=%d]\n", mxt->valid_irq_counter, mxt->invalid_irq_counter ); bufp += sprintf(bufp, "Messages:\t[%d]\n", mxt->message_counter); bufp += sprintf(bufp, "Read Failures:\t[%d]\n", mxt->read_fail_counter); return strlen(buf); } static ssize_t show_object_info(struct device *dev, struct device_attribute *attr, char *buf) { struct i2c_client *client; struct mxt_data *mxt; char *bufp; struct mxt_object *object_table; int i; client = to_i2c_client(dev); mxt = i2c_get_clientdata(client); object_table = mxt->object_table; bufp = buf; bufp += sprintf(bufp, "maXTouch: %d Objects\n", mxt->device_info.num_objs); for (i = 0; i < MXT_MAX_OBJECT_TYPES; i++) { if (object_table[i].type != 0) { bufp += sprintf(bufp, "Type:\t\t[%d]: %s\n", object_table[i].type, object_type_name[i]); bufp += sprintf(bufp, "Address:\t0x%04X\n", object_table[i].chip_addr); bufp += sprintf(bufp, "Size:\t\t%d Bytes\n", object_table[i].size); bufp += sprintf(bufp, "Instances:\t%d\n", object_table[i].instances ); bufp += sprintf(bufp, "Report Id's:\t%d\n\n", object_table[i].num_report_ids); } } return strlen(buf); } static ssize_t show_messages(struct device *dev, struct device_attribute *attr, char *buf) { struct i2c_client *client; struct mxt_data *mxt; struct mxt_object *object_table; int i; __u8 *message; __u16 message_len; __u16 message_addr; char *bufp; client = to_i2c_client(dev); mxt = i2c_get_clientdata(client); object_table = mxt->object_table; bufp = buf; message = kmalloc(mxt->message_size, GFP_KERNEL); if (message == NULL) { printk(KERN_DEBUG "Error allocating memory!\n"); return -ENOMEM; } message_addr = mxt->msg_proc_addr; message_len = mxt->message_size; bufp += sprintf(bufp, "Reading Message Window [0x%04x]\n", message_addr); #if 0 /* Acquire the lock. */ if (down_interruptible(&mxt->msg_sem)) { printk(KERN_DEBUG "mxt: Interrupted while waiting for mutex!\n"); kfree(message); return -ERESTARTSYS; } #endif while (mxt->new_msgs == 0) { /* Release the lock. */ #if 0 up(&mxt->msg_sem); #endif if (wait_event_interruptible(mxt->msg_queue, mxt->new_msgs)) { printk(KERN_DEBUG "mxt: Interrupted while waiting for new msg!\n"); kfree(message); return -ERESTARTSYS; } #if 0 /* Acquire the lock. */ if (down_interruptible(&mxt->msg_sem)) { printk(KERN_DEBUG "mxt: Interrupted while waiting for mutex!\n"); kfree(message); return -ERESTARTSYS; } #endif } for (i = 0; i < mxt->message_size; i++) message[i] = mxt->last_message[i]; mxt->new_msgs = 0; #if 0 /* Release the lock. */ up(&mxt->msg_sem); #endif for (i = 0; i < message_len; i++) bufp += sprintf(bufp, "0x%02x ", message[i]); bufp--; bufp += sprintf(bufp, "\t%s\n", REPORT_ID_TO_OBJECT_NAME(message[0])); kfree(message); return strlen(buf); } static ssize_t show_report_id(struct device *dev, struct device_attribute *attr, char *buf) { struct i2c_client *client; struct mxt_data *mxt; struct report_id_map *report_id; int i; int object; char *bufp; client = to_i2c_client(dev); mxt = i2c_get_clientdata(client); report_id = mxt->rid_map; bufp = buf; for (i = 0 ; i < mxt->report_id_count ; i++) { object = report_id[i].object; bufp += sprintf(bufp, "Report Id [%03d], object [%03d], " "instance [%03d]:\t%s\n", i, object, report_id[i].instance, object_type_name[object]); } return strlen(buf); } static ssize_t set_debug(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int state; sscanf(buf, "%d", &state); if (state == 0 || state == 1) { if (state) { debug = DEBUG_TRACE; printk(KERN_DEBUG "touch info enabled"); } else { debug = DEBUG_INFO; printk(KERN_DEBUG "touch info disabled"); } } else { return -EINVAL; } return count; } static ssize_t show_firmware_dev(struct device *dev, struct device_attribute *attr, char *buf) { struct mxt_data *mxt = dev_get_drvdata(dev); u8 val[7]; mxt_read_block(mxt->client, MXT_ADDR_INFO_BLOCK, 7, (u8 *)val); mxt->device_info.major = ((val[2] >> 4) & 0x0F); mxt->device_info.minor = (val[2] & 0x0F); mxt->device_info.build = val[3]; return snprintf(buf, PAGE_SIZE, "ATM_%d.%dx%d\n", mxt->device_info.major, mxt->device_info.minor, mxt->device_info.build); } static ssize_t store_firmware(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int state; struct mxt_data *mxt = dev_get_drvdata(dev); if (sscanf(buf, "%i", &state) != 1 || (state < 0 || state > 1)) return -EINVAL; /*prevents the system from entering suspend during updating*/ wake_lock(&mxt->wakelock); disable_irq(mxt->client->irq); mxt_load_firmware(dev, MXT1386_FIRMWARE); enable_irq(mxt->client->irq); wake_unlock(&mxt->wakelock); return count; } static ssize_t show_firmware_bin(struct device *dev, struct device_attribute *attr, char *buf) { int ver[2]; mxt_check_firmware(dev, ver); return snprintf(buf, PAGE_SIZE, "ATM_%d.%dx%d\n", ver[0]/16, ver[0]%16, ver[1]); } static int chk_obj(u8 type) { switch (type) { /* case MXT_GEN_MESSAGEPROCESSOR_T5:*/ /* case MXT_GEN_COMMANDPROCESSOR_T6:*/ case MXT_GEN_POWERCONFIG_T7: case MXT_GEN_ACQUIRECONFIG_T8: case MXT_TOUCH_MULTITOUCHSCREEN_T9: case MXT_TOUCH_KEYARRAY_T15: case MXT_SPT_COMMSCONFIG_T18: case MXT_PROCG_NOISESUPPRESSION_T22: case MXT_PROCI_ONETOUCHGESTUREPROCESSOR_T24: case MXT_SPT_SELFTEST_T25: case MXT_PROCI_TWOTOUCHGESTUREPROCESSOR_T27: case MXT_SPT_CTECONFIG_T28: /* case MXT_DEBUG_DIAGNOSTICS_T37:*/ /* case MXT_USER_INFO_T38:*/ /* case MXT_GEN_EXTENSION_T39:*/ case MXT_PROCI_GRIPSUPPRESSION_T40: case MXT_PROCI_PALMSUPPRESSION_T41: case MXT_SPT_DIGITIZER_T43: /* case MXT_MESSAGECOUNT_T44:*/ return 0; default: return -1; } } static ssize_t show_object(struct device *dev, struct device_attribute *attr, char *buf) { /* struct qt602240_data *data = dev_get_drvdata(dev);*/ /* struct qt602240_object *object;*/ struct mxt_data *mxt; struct mxt_object *object_table; int count = 0; int i, j; u8 val; mxt = dev_get_drvdata(dev); object_table = mxt->object_table; for (i = 0; i < mxt->device_info.num_objs; i++) { u8 obj_type = object_table[i].type; if (chk_obj(obj_type)) continue; count += sprintf(buf + count, "%s: %d bytes\n", object_type_name[obj_type], object_table[i].size); for (j = 0; j < object_table[i].size; j++) { mxt_read_byte(mxt->client, MXT_BASE_ADDR(obj_type)+(u16)j, &val); count += sprintf(buf + count, " Byte %2d: 0x%02x (%d)\n", j, val, val); } count += sprintf(buf + count, "\n"); } #ifdef MXT_TUNNING_ENABLE backup_to_nv(mxt); #endif return count; } static ssize_t store_object(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { /* struct qt602240_data *data = dev_get_drvdata(dev);*/ /* struct qt602240_object *object;*/ struct mxt_data *mxt; /* struct mxt_object *object_table;*/ unsigned int type, offset, val; u16 chip_addr; int ret; mxt = dev_get_drvdata(dev); if ((sscanf(buf, "%u %u %u", &type, &offset, &val) != 3) || (type >= MXT_MAX_OBJECT_TYPES)) { pr_err("Invalid values"); return -EINVAL; } printk(KERN_DEBUG "Object type: %u, Offset: %u, Value: %u\n", type, offset, val); chip_addr = get_object_address(type, 0, mxt->object_table, mxt->device_info.num_objs); if (chip_addr == 0) { pr_err("Invalid object type(%d)!", type); return -EIO; } ret = mxt_write_byte(mxt->client, chip_addr+(u16)offset, (u8)val); if (ret < 0) return ret; return count; } #ifdef ITDEV static ssize_t pause_show(struct device *dev, struct device_attribute *attr, char *buf) { int count = 0; count += sprintf(buf + count, "%d", driver_paused); count += sprintf(buf + count, "\n"); return count; } static ssize_t pause_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int i; if (sscanf(buf, "%u", &i) == 1 && i < 2) { driver_paused = i; printk(KERN_DEBUG "%s\n", i ? "paused" : "unpaused"); } else printk(KERN_DEBUG "pause_driver write error\n"); return count; } static ssize_t debug_enable_show(struct device *dev, struct device_attribute *attr, char *buf) { int count = 0; count += sprintf(buf + count, "%d", debug_enabled); count += sprintf(buf + count, "\n"); return count; } static ssize_t debug_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int i; if (sscanf(buf, "%u", &i) == 1 && i < 2) { debug_enabled = i; printk(KERN_DEBUG "%s\n", i ? "debug enabled" : "debug disabled"); } else printk(KERN_DEBUG "debug_enabled write error\n"); return count; } static ssize_t command_calibrate_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct i2c_client *client; struct mxt_data *mxt; int ret; client = to_i2c_client(dev); mxt = i2c_get_clientdata(client); ret = mxt_write_byte(client, MXT_BASE_ADDR(MXT_GEN_COMMANDPROCESSOR_T6) + MXT_ADR_T6_CALIBRATE, 0x1); return (ret < 0) ? ret : count; } static ssize_t command_reset_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct i2c_client *client; struct mxt_data *mxt; int ret; client = to_i2c_client(dev); mxt = i2c_get_clientdata(client); ret = reset_chip(mxt, RESET_TO_NORMAL); return (ret < 0) ? ret : count; } static ssize_t command_backup_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct i2c_client *client; struct mxt_data *mxt; int ret; client = to_i2c_client(dev); mxt = i2c_get_clientdata(client); ret = backup_to_nv(mxt); return (ret < 0) ? ret : count; } /* Sysfs files for libmaxtouch interface */ static DEVICE_ATTR(pause_driver, 0666, pause_show, pause_store); static DEVICE_ATTR(debug_enable, 0666, debug_enable_show, debug_enable_store); static DEVICE_ATTR(command_calibrate, 0666, NULL, command_calibrate_store); static DEVICE_ATTR(command_reset, 0666, NULL, command_reset_store); static DEVICE_ATTR(command_backup, 0666, NULL, command_backup_store); static struct attribute *libmaxtouch_attributes[] = { &dev_attr_pause_driver.attr, &dev_attr_debug_enable.attr, &dev_attr_command_calibrate.attr, &dev_attr_command_reset.attr, &dev_attr_command_backup.attr, NULL, }; static struct attribute_group libmaxtouch_attr_group = { .attrs = libmaxtouch_attributes, }; #endif static int enter_debug_mode(struct mxt_data *mxt, u8 cmd) { int try_cnt = 0; u8 mode = 0; u16 cmd_addr = T6_REG(MXT_ADR_T6_DIAGNOSTICS); u16 diagnostic_addr = MXT_BASE_ADDR(MXT_DEBUG_DIAGNOSTICS_T37); /* Page Num Clear */ mxt_write_byte(mxt->client, cmd_addr, MXT_CMD_T6_CTE_MODE); msleep(20); mxt_write_byte(mxt->client, cmd_addr, cmd); msleep(20); /* check the mode */ do { mxt_read_byte(mxt->client, diagnostic_addr, &mode); if (cmd == mode) { printk(KERN_DEBUG "[TSP] debug mode : %s\n", cmd == MXT_CMD_T6_REFERENCES_MODE ? "reference" : "delta"); return 0; } try_cnt++; msleep(20); } while (try_cnt < 5); return -EAGAIN; } static int read_all_refdata(struct mxt_data *mxt) { int status = -EAGAIN, try_cnt = 0; u8 mode = 0, read_page = 0, read_point = 0, max_page_slave = 0, numofch = 0; u8 dbg_data[MXT1386_PAGE_SIZE * 2]; u16 max_val = MXT1386_MIN_REF_VALUE, min_val = MXT1386_MAX_REF_VALUE, ref_val = 0; const u16 cmd_addr = T6_REG(MXT_ADR_T6_DIAGNOSTICS); const u16 diagnostic_addr = MXT_BASE_ADDR(MXT_DEBUG_DIAGNOSTICS_T37); mxt->index = 0; if (enter_debug_mode(mxt, MXT_CMD_T6_REFERENCES_MODE)) return -EAGAIN; max_page_slave = (u8)((mxt->pdata->touchscreen_config.xsize * MXT1386_PAGE_WIDTH) / MXT1386_PAGE_SIZE); do { if (MXT1386_MAX_PAGE == read_page) { if (1 != status) status = 0; break; } if ((read_page % MXT1386_PAGE_SIZE_SLAVE) < max_page_slave) numofch = (u8)(MXT1386_PAGE_SIZE * 2); else if ((read_page % MXT1386_PAGE_SIZE_SLAVE) == max_page_slave) numofch = (u8)(((mxt->pdata->touchscreen_config.xsize * MXT1386_PAGE_WIDTH) - (max_page_slave * MXT1386_PAGE_SIZE)) * 2); else { read_page++; mxt_write_byte(mxt->client, cmd_addr, MXT_CMD_T6_PAGE_UP); msleep(20); continue; } mxt_read_byte(mxt->client, diagnostic_addr+1, &mode); if (mode == read_page) { mxt_read_block(mxt->client, diagnostic_addr + 2, numofch, dbg_data); for (read_point = 0; read_point < numofch; read_point += 2) { ref_val = (u16)dbg_data[read_point] | (u16)dbg_data[read_point+1] << 8; if (ref_val > MXT1386_MAX_REF_VALUE) { max_val = ref_val; status = 1; } else if (ref_val < MXT1386_MIN_REF_VALUE) { min_val = ref_val; status = 1; } /* printk(KERN_DEBUG "[TSP] page : %u, node : %u," "ref : %u\n", mode, read_point, ref_val); */ if (ref_val > max_val) max_val = ref_val; else if (ref_val < min_val) min_val = ref_val; mxt->ref_data[mxt->index++] = ref_val; } read_page++; mxt_write_byte(mxt->client, cmd_addr, MXT_CMD_T6_PAGE_UP); msleep(20); } else { try_cnt++; if (mode < read_page) mxt_write_byte(mxt->client, cmd_addr, MXT_CMD_T6_PAGE_UP); msleep(20); } } while (try_cnt < 10); printk(KERN_DEBUG "[TSP] max_val : %d," " min_val : %u status : %u\n", max_val, min_val, status); return status; } static void read_all_deltadata(struct mxt_data *mxt) { int try_cnt = 0; u8 mode = 0, read_page = 0, read_point = 0, max_page_slave = 0, numofch = 0; u8 dbg_data[MXT1386_PAGE_SIZE * 2]; u16 delta_val = 0; const u16 cmd_addr = T6_REG(MXT_ADR_T6_DIAGNOSTICS); const u16 diagnostic_addr = MXT_BASE_ADDR(MXT_DEBUG_DIAGNOSTICS_T37); mxt->index = 0; enter_debug_mode(mxt, MXT_CMD_T6_DELTAS_MODE); max_page_slave = (mxt->pdata->touchscreen_config.xsize * MXT1386_PAGE_WIDTH) / MXT1386_PAGE_SIZE; do { if (MXT1386_MAX_PAGE == read_page) break; if ((read_page % MXT1386_PAGE_SIZE_SLAVE) < max_page_slave) numofch = (u8)(MXT1386_PAGE_SIZE * 2); else if ((read_page % MXT1386_PAGE_SIZE_SLAVE) == max_page_slave) numofch = (u8)(((mxt->pdata->touchscreen_config.xsize * MXT1386_PAGE_WIDTH) - (max_page_slave * MXT1386_PAGE_SIZE)) * 2); else { read_page++; mxt_write_byte(mxt->client, cmd_addr, MXT_CMD_T6_PAGE_UP); msleep(20); continue; } mxt_read_byte(mxt->client, diagnostic_addr+1, &mode); if (mode == read_page) { mxt_read_block(mxt->client, diagnostic_addr + 2, numofch, dbg_data); for (read_point = 0; read_point < numofch; read_point += 2) { delta_val = (u16)dbg_data[read_point] | (u16)dbg_data[read_point+1] << 8; mxt->delta_data[mxt->index++] = delta_val; } read_page++; mxt_write_byte(mxt->client, cmd_addr, MXT_CMD_T6_PAGE_UP); msleep(20); } else { try_cnt++; msleep(20); } } while (try_cnt < 10); } static void mxt_read_2byte(u16 Address, u16 *Data, struct mxt_data *mxt) { u8 temp[2]; mxt_read_block(mxt->client, Address, 2, temp); *Data = ((uint16_t)temp[1]<<8) + (uint16_t)temp[0]; } static void check_debug_data(struct mxt_data *mxt, u16 node, u8 mode) { int try_cnt = 0; u8 read_page = 0, read_point = 0, current_page = 0, value = 0; u16 debug_val = 0; const u16 cmd_addr = T6_REG(MXT_ADR_T6_DIAGNOSTICS); const u16 diagnostic_addr = MXT_BASE_ADDR(MXT_DEBUG_DIAGNOSTICS_T37); enter_debug_mode(mxt, mode); read_page = node / 64; read_point = ((node % 64) * 2) + 2; do { if (current_page == read_page) break; mxt_read_byte(mxt->client, diagnostic_addr+1, &value); if (current_page == value) current_page++; else { try_cnt++; msleep(20); continue; } mxt_write_byte(mxt->client, cmd_addr, MXT_CMD_T6_PAGE_UP); msleep(20); } while (try_cnt < 10); mxt_read_2byte(diagnostic_addr + read_point, &debug_val, mxt); if (MXT_CMD_T6_REFERENCES_MODE == mode) mxt->ref_data[node] = debug_val; else if (MXT_CMD_T6_DELTAS_MODE == mode) mxt->delta_data[node] = debug_val; printk(KERN_DEBUG "[TSP] %s[%d] : %d\n", mode == MXT_CMD_T6_REFERENCES_MODE ? "ref" : "delta", node, debug_val); } static int check_all_refer(struct mxt_data *mxt) { int ret = 0; int try_cnt = 0; do { if (!mxt->set_mode_for_ta) mxt_write_byte(mxt->client, MXT_BASE_ADDR(MXT_GEN_POWERCONFIG_T7) + MXT_ADR_T7_IDLEACQINT, 0xff); msleep(20); ret = read_all_refdata(mxt); printk(KERN_DEBUG "[TSP] ret : %d\n", ret); if (-EAGAIN != ret) { printk(KERN_DEBUG "[TSP] status : %d\n", ret); reset_chip(mxt, RESET_TO_NORMAL); msleep(300); mxt->pdata->fherr_cnt = 0; mxt->pdata->fherr_cnt_no_ta = 0; if (!work_pending(&mxt->ta_work)) schedule_work(&mxt->ta_work); return ret; } printk(KERN_DEBUG "[TSP] failed to enter the debug mode : %d\n", ++try_cnt); } while (try_cnt < 5); if (!mxt->set_mode_for_ta) mxt_write_byte(mxt->client, MXT_BASE_ADDR(MXT_GEN_POWERCONFIG_T7) + MXT_ADR_T7_IDLEACQINT, mxt->pdata->power_config.idleacqint); return 1; } static void check_index(struct mxt_data *mxt) { if (mxt->index > MXT1386_MAX_CHANNEL) mxt->index = 0; } static void get_index(struct mxt_data *mxt, const char *str) { u32 tmp; sscanf(str, "%u", &tmp); mxt->index = tmp; printk(KERN_DEBUG "[TSP] mxt->index : %u\n", tmp); } static void set_fhe_chg_cnt(struct mxt_data *mxt, const char *str) { u32 tmp; sscanf(str, "%u", &tmp); mxt->pdata->fherr_chg_cnt = tmp; printk(KERN_DEBUG "[TSP] mxt->pdata->fherr_chg_cnt : %u\n", tmp); } static void set_mxt_update_exe(struct work_struct *work) { struct mxt_data *mxt = container_of(work, struct mxt_data, firmup_dwork.work); int ret, cnt; printk(KERN_DEBUG "[TSP]%s\n", __func__); /*wake_lock(&mxt->wakelock); */ disable_irq(mxt->client->irq); /*disable interrupt*/ ret = mxt_load_firmware(&mxt->client->dev, MXT1386_FIRMWARE); enable_irq(mxt->client->irq); /*enable interrupt*/ /*wake_unlock(&mxt->wakelock);*/ if (ret >= 0) { for (cnt = 10; cnt > 0; cnt--) { if (mxt->firm_normal_status_ack == 1) { /* firmware update success*/ mxt->firm_status_data = 2; printk(KERN_DEBUG "[TSP]Reprogram done : Firmware update Success~~~~~~~~~~\n"); break; } else { printk(KERN_DEBUG "[TSP]Reprogram done , but not yet normal status : 3s delay needed\n"); msleep(3000);/*3s delay*/ } } if (cnt == 0) { /* firmware update Fail */ mxt->firm_status_data = 3; printk(KERN_DEBUG "[TSP]Reprogram done : Firmware update Fail ~~~~~~~~~~\n"); } } else { /* firmware update Fail*/ mxt->firm_status_data = 3; printk(KERN_DEBUG "[TSP]Reprogram done : Firmware update Fail~~~~~~~~~~\n"); } mxt->firm_normal_status_ack = 0; } static ssize_t set_mxt_update_show(struct device *dev, struct device_attribute *attr, char *buf) { int count; struct mxt_data *mxt = dev_get_drvdata(dev); printk(KERN_DEBUG "[TSP]%s\n", __func__); /*start firmware updating*/ mxt->firm_status_data = 1; cancel_delayed_work(&mxt->firmup_dwork); schedule_delayed_work(&mxt->firmup_dwork, 0); if (mxt->firm_status_data == 3) count = sprintf(buf, "FAIL\n"); else count = sprintf(buf, "OK\n"); return count; } /*Current(Panel) Version*/ static ssize_t set_mxt_firm_version_read_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mxt_data *mxt = dev_get_drvdata(dev); int error, cnt; u8 val[7]; u8 fw_current_version; for (cnt = 10; cnt > 0; cnt--) { error = mxt_read_block(mxt->client, MXT_ADDR_INFO_BLOCK, 7, (u8 *)val); if (error < 0) { printk(KERN_DEBUG "Atmel touch version read fail , it will try 2s later"); msleep(2000); } else { break; } } if (cnt == 0) { pr_err("set_mxt_firm_version_show failed!!!"); fw_current_version = 0; } mxt->device_info.major = ((val[2] >> 4) & 0x0F); mxt->device_info.minor = (val[2] & 0x0F); mxt->device_info.build = val[3]; fw_current_version = val[2]; printk(KERN_DEBUG "[TSP] Atmel %s Firmware version [%d.%d](%d) Build %d\n", mxt224_variant, mxt->device_info.major, mxt->device_info.minor, fw_current_version, mxt->device_info.build); return sprintf(buf, "%02d\n", fw_current_version); } /*Last(Phone) Version*/ static ssize_t set_mxt_firm_version_show(struct device *dev, struct device_attribute *attr, char *buf) { u8 fw_latest_version; fw_latest_version = firmware_latest[0]; printk(KERN_DEBUG "Atmel Last firmware version is %d\n", fw_latest_version); return sprintf(buf, "%02d\n", fw_latest_version); } static ssize_t set_mxt_firm_status_show(struct device *dev, struct device_attribute *attr, char *buf) { int count; struct mxt_data *mxt = dev_get_drvdata(dev); printk(KERN_DEBUG "Enter firmware_status_show by Factory command\n"); if (mxt->firm_status_data == 1) count = sprintf(buf, "Downloading\n"); else if (mxt->firm_status_data == 2) count = sprintf(buf, "PASS\n"); else if (mxt->firm_status_data == 3) count = sprintf(buf, "FAIL\n"); else count = sprintf(buf, "PASS\n"); return count; } static ssize_t show_threshold(struct device *dev, struct device_attribute *attr, char *buf) { struct mxt_data *mxt = dev_get_drvdata(dev); if (mxt->set_mode_for_ta) return sprintf(buf, "%d\n", mxt->pdata->tchthr_for_ta_connect); else return sprintf(buf, "%d\n", mxt->pdata->touchscreen_config.tchthr); } static ssize_t store_threshold(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct mxt_data *mxt = dev_get_drvdata(dev); int i; if (sscanf(buf, "%d", &i) == 1) { /* prevents the system from entering suspend during updating*/ wake_lock(&mxt->wakelock); disable_irq(mxt->client->irq); mxt->pdata->touchscreen_config.tchthr = i;/*basically,48*/ mxt_multitouch_config(mxt); /* backup to nv memory */ backup_to_nv(mxt); /* forces a reset of the chipset */ reset_chip(mxt, RESET_TO_NORMAL); msleep(250); enable_irq(mxt->client->irq); wake_unlock(&mxt->wakelock); printk(KERN_DEBUG "[TSP] threshold is changed to %d\n", i); } else { pr_err("[TSP] threshold write error\n"); } return size; } static ssize_t set_suppression_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mxt_data *mxt = dev_get_drvdata(dev); u8 val; mxt_read_byte(mxt->client, MXT_BASE_ADDR(MXT_PROCI_PALMSUPPRESSION_T41), &val); return sprintf(buf, "%d\n", val); } static ssize_t set_suppression_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct mxt_data *mxt = dev_get_drvdata(dev); int i; if (sscanf(buf, "%d", &i) == 1) { if (0x81 == i) { mxt_write_byte(mxt->client, MXT_BASE_ADDR(MXT_PROCI_PALMSUPPRESSION_T41), 0x0); printk(KERN_DEBUG "[TSP] the palm suppression field is off\n"); } else { mxt_write_byte(mxt->client, MXT_BASE_ADDR(MXT_PROCI_PALMSUPPRESSION_T41), mxt->pdata->palmsupression_config.ctrl); printk(KERN_DEBUG "[TSP] the palm suppression field is on\n"); } } else { printk(KERN_DEBUG "[TSP] sysfs write error\n"); } return size; } #define SET_SHOW_FN(name, fn, format, ...) \ static ssize_t show_##name(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ struct mxt_data *mxt = dev_get_drvdata(dev); \ if (NULL == mxt) { \ pr_err("[TSP] drvdata is not set\n"); \ return sprintf(buf, "\n"); \ } \ fn; \ return sprintf(buf, format "\n", ## __VA_ARGS__); \ } #define SET_STORE_FN(name, fn) \ static ssize_t store_##name(struct device *dev, \ struct device_attribute *attr, \ const char *buf, size_t size) \ { \ struct mxt_data *mxt = dev_get_drvdata(dev); \ if (NULL == mxt) { \ pr_err("[TSP] drvdata is not set\n"); \ return size; \ } \ fn(mxt, buf); \ return size; \ } #define ATTR_SHOW_REF(num, node) \ SET_SHOW_FN(set_refer##num, \ check_debug_data(mxt, node, MXT_CMD_T6_REFERENCES_MODE), \ "%u", mxt->ref_data[node]) #define ATTR_SHOW_DELTA(num, node) \ SET_SHOW_FN(set_delta##num, \ check_debug_data(mxt, node, MXT_CMD_T6_DELTAS_MODE), \ "%u", mxt->delta_data[node]) static int check_family_id(struct mxt_data *mxt) { return mxt->device_info.family_id; } /* sec_touchscreen */ SET_SHOW_FN(mxt_touchtype, printk(KERN_DEBUG "[TSP] %s\n", __func__), "ATMEL,MXT1386"); SET_SHOW_FN(fhe_chg_cnt, printk(KERN_DEBUG "[TSP] %s\n", __func__), "%d", mxt->pdata->fherr_chg_cnt); SET_STORE_FN(fhe_chg_cnt, set_fhe_chg_cnt); static DEVICE_ATTR(mxt_touchtype, S_IRUGO, show_mxt_touchtype, NULL); static DEVICE_ATTR(fhe_chg_cnt, S_IRUGO | S_IWUSR, show_fhe_chg_cnt, store_fhe_chg_cnt); /* tsp_noise_test */ SET_SHOW_FN(set_module_off, mxt->pdata->suspend_platform_hw(), "tspoff"); SET_SHOW_FN(set_module_on, mxt->pdata->resume_platform_hw(), "tspon"); SET_SHOW_FN(x_line, printk(KERN_DEBUG "[TSP] %s\n", __func__), "%d", mxt->pdata->touchscreen_config.xsize); SET_SHOW_FN(y_line, printk(KERN_DEBUG "[TSP] %s\n", __func__), "%d", mxt->pdata->touchscreen_config.ysize); SET_SHOW_FN(set_all_refer, printk(KERN_DEBUG "[TSP] %s\n", __func__), "%d", check_all_refer(mxt)); SET_SHOW_FN(set_all_delta, read_all_deltadata(mxt), "set_all_delta"); SET_SHOW_FN(disp_all_refdata, check_index(mxt), "%u", mxt->ref_data[mxt->index]); SET_SHOW_FN(disp_all_deltadata, check_index(mxt), "%u", mxt->delta_data[mxt->index]); SET_SHOW_FN(set_firm_version, printk(KERN_DEBUG "[TSP] %s\n", __func__), "%d", check_family_id(mxt)); SET_STORE_FN(disp_all_refdata, get_index); SET_STORE_FN(disp_all_deltadata, get_index); ATTR_SHOW_REF(0, 324); ATTR_SHOW_REF(1, 45); ATTR_SHOW_REF(2, 700); ATTR_SHOW_REF(3, 1355); ATTR_SHOW_REF(4, 1075); ATTR_SHOW_DELTA(0, 324); ATTR_SHOW_DELTA(1, 45); ATTR_SHOW_DELTA(2, 700); ATTR_SHOW_DELTA(3, 1355); ATTR_SHOW_DELTA(4, 1075); /* Register sysfs files */ static DEVICE_ATTR(deltas, S_IRUGO, show_deltas, NULL); static DEVICE_ATTR(references, S_IRUGO, show_references, NULL); static DEVICE_ATTR(device_info, S_IRUGO, show_device_info, NULL); static DEVICE_ATTR(object_info, S_IRUGO, show_object_info, NULL); static DEVICE_ATTR(messages, S_IRUGO, show_messages, NULL); static DEVICE_ATTR(report_id, S_IRUGO, show_report_id, NULL); static DEVICE_ATTR(stat, S_IRUGO, show_stat, NULL); static DEVICE_ATTR(config, S_IWUSR | S_IRUGO, get_config, set_config); static DEVICE_ATTR(ap, S_IWUSR, NULL, set_ap); static DEVICE_ATTR(debug, S_IWUSR, NULL, set_debug); static DEVICE_ATTR(fw_dev, S_IWUSR | S_IRUGO, show_firmware_dev, store_firmware); static DEVICE_ATTR(fw_bin, S_IRUGO, show_firmware_bin, NULL); static DEVICE_ATTR(object, S_IWUSR | S_IRUGO, show_object, store_object); static DEVICE_ATTR(set_module_off, S_IRUGO, show_set_module_off, NULL); static DEVICE_ATTR(set_module_on, S_IRUGO, show_set_module_on, NULL); static DEVICE_ATTR(x_line, S_IRUGO, show_x_line, NULL); static DEVICE_ATTR(y_line, S_IRUGO, show_y_line, NULL); static DEVICE_ATTR(set_all_refer, S_IRUGO, show_set_all_refer, NULL); static DEVICE_ATTR(set_all_delta, S_IRUGO, show_set_all_delta, NULL); static DEVICE_ATTR(disp_all_refdata, S_IRUGO | S_IWUSR | S_IWGRP, show_disp_all_refdata, store_disp_all_refdata); static DEVICE_ATTR(disp_all_deltadata, S_IRUGO | S_IWUSR | S_IWGRP, show_disp_all_deltadata, store_disp_all_deltadata); static DEVICE_ATTR(set_refer0, S_IRUGO, show_set_refer0, NULL); static DEVICE_ATTR(set_delta0, S_IRUGO, show_set_delta0, NULL); static DEVICE_ATTR(set_refer1, S_IRUGO, show_set_refer1, NULL); static DEVICE_ATTR(set_delta1, S_IRUGO, show_set_delta1, NULL); static DEVICE_ATTR(set_refer2, S_IRUGO, show_set_refer2, NULL); static DEVICE_ATTR(set_delta2, S_IRUGO, show_set_delta2, NULL); static DEVICE_ATTR(set_refer3, S_IRUGO, show_set_refer3, NULL); static DEVICE_ATTR(set_delta3, S_IRUGO, show_set_delta3, NULL); static DEVICE_ATTR(set_refer4, S_IRUGO, show_set_refer4, NULL); static DEVICE_ATTR(set_delta4, S_IRUGO, show_set_delta4, NULL); static DEVICE_ATTR(tsp_firm_update, S_IRUGO, set_mxt_update_show, NULL); static DEVICE_ATTR(tsp_firm_update_status, S_IRUGO, set_mxt_firm_status_show, NULL); static DEVICE_ATTR(tsp_threshold, S_IRUGO | S_IWUSR, show_threshold, store_threshold); static DEVICE_ATTR(tsp_firm_version_phone, S_IRUGO, set_mxt_firm_version_show, NULL); static DEVICE_ATTR(tsp_firm_version_panel, S_IRUGO, set_mxt_firm_version_read_show, NULL); static DEVICE_ATTR(set_suppression, S_IRUGO | S_IWUSR, set_suppression_show, set_suppression_store); static DEVICE_ATTR(set_firm_version, S_IRUGO, show_set_firm_version, NULL); static struct attribute *maxTouch_attributes[] = { &dev_attr_deltas.attr, &dev_attr_references.attr, &dev_attr_device_info.attr, &dev_attr_object_info.attr, &dev_attr_messages.attr, &dev_attr_report_id.attr, &dev_attr_stat.attr, &dev_attr_config.attr, &dev_attr_ap.attr, &dev_attr_debug.attr, &dev_attr_fw_dev.attr, &dev_attr_fw_bin.attr, &dev_attr_object.attr, &dev_attr_mxt_touchtype.attr, &dev_attr_fhe_chg_cnt.attr, &dev_attr_set_module_off.attr, &dev_attr_set_module_on.attr, &dev_attr_x_line.attr, &dev_attr_y_line.attr, &dev_attr_set_all_refer.attr, &dev_attr_set_all_delta.attr, &dev_attr_disp_all_refdata.attr, &dev_attr_disp_all_deltadata.attr, &dev_attr_set_refer0.attr, &dev_attr_set_delta0.attr, &dev_attr_set_refer1.attr, &dev_attr_set_delta1.attr, &dev_attr_set_refer2.attr, &dev_attr_set_delta2.attr, &dev_attr_set_refer3.attr, &dev_attr_set_delta3.attr, &dev_attr_set_refer4.attr, &dev_attr_set_delta4.attr, &dev_attr_tsp_firm_update.attr, &dev_attr_tsp_firm_update_status.attr, &dev_attr_tsp_threshold.attr, &dev_attr_tsp_firm_version_phone.attr, &dev_attr_tsp_firm_version_panel.attr, &dev_attr_set_suppression.attr, &dev_attr_set_firm_version.attr, NULL, }; static struct attribute_group maxtouch_attr_group = { .attrs = maxTouch_attributes, }; /******************************************************************************/ /* Initialization of driver */ /******************************************************************************/ static int __devinit mxt_identify(struct i2c_client *client, struct mxt_data *mxt) { u8 buf[7]; int error; int identified; identified = 0; retry_i2c: /* Read Device info to check if chip is valid */ error = mxt_read_block(client, MXT_ADDR_INFO_BLOCK, 7, (u8 *) buf); if (error < 0) { mxt->read_fail_counter++; if (mxt->read_fail_counter < 3) { msleep(30); goto retry_i2c; } dev_err(&client->dev, "Failure accessing maXTouch device\n"); return -EIO; } 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 Info */ if (mxt->device_info.family_id == MAXTOUCH_FAMILYID) { strlcpy(mxt->device_info.family, maxtouch_family, sizeof(mxt->device_info.family)); } else { dev_err(&client->dev, "maXTouch Family ID [0x%x] not supported\n", mxt->device_info.family_id); identified = -ENXIO; } /* Check Variant Info */ if ((mxt->device_info.variant_id == MXT224_CAL_VARIANTID) || (mxt->device_info.variant_id == MXT224_UNCAL_VARIANTID)) { strlcpy(mxt->device_info.variant, maxtouch_family, sizeof(mxt->device_info.variant)); } else { dev_err(&client->dev, "maXTouch Variant ID [0x%x] not supported\n", mxt->device_info.variant_id); identified = -ENXIO; } printk(KERN_DEBUG "[TSP] Atmel %s.%s\n", mxt->device_info.family, mxt->device_info.variant ); printk(KERN_DEBUG "[TSP] Firmware version [%d.%d] Build %d\n", mxt->device_info.major, mxt->device_info.minor, mxt->device_info.build ); printk(KERN_DEBUG "[TSP] Configuration [X: %d] x [Y: %d]\n", mxt->device_info.x_size, mxt->device_info.y_size ); printk(KERN_DEBUG "[TSP] number of objects: %d\n", mxt->device_info.num_objs ); return identified; } /* * Reads the object table from maXTouch chip to get object data like * address, size, report id. */ static int __devinit mxt_read_object_table(struct i2c_client *client, struct mxt_data *mxt) { u16 report_id_count; u8 buf[MXT_OBJECT_TABLE_ELEMENT_SIZE]; u8 object_type; u16 object_address; u16 object_size; u8 object_instances; u8 object_report_ids; u16 object_info_address; u32 crc; u32 crc_calculated = 0; int i; int error; u8 object_instance; u8 object_report_id; u8 report_id; int first_report_id; struct mxt_object *object_table; if (debug >= DEBUG_TRACE) printk(KERN_DEBUG "[TSP] maXTouch driver get configuration\n"); object_table = kzalloc(sizeof(struct mxt_object) * mxt->device_info.num_objs, GFP_KERNEL); if (object_table == NULL) { pr_err("maXTouch: Memory allocation failed!\n"); return -ENOMEM; } mxt->object_table = object_table; if (debug >= DEBUG_TRACE) printk(KERN_DEBUG "[TSP] maXTouch driver Memory allocated\n"); object_info_address = MXT_ADDR_OBJECT_TABLE; report_id_count = 0; for (i = 0; i < mxt->device_info.num_objs; i++) { if (debug >= DEBUG_TRACE) printk(KERN_DEBUG "[TSP] Reading maXTouch at [0x%04x]: ", object_info_address); retry_i2c: error = mxt_read_block(client, object_info_address, MXT_OBJECT_TABLE_ELEMENT_SIZE, (u8 *)buf); if (error < 0) { mxt->read_fail_counter++; if (mxt->read_fail_counter < 3) goto retry_i2c; dev_err(&client->dev, "maXTouch Object %d could not be read\n", i); return -EIO; } 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]; if (debug >= DEBUG_TRACE) printk(KERN_DEBUG "[TSP] 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 ); if (object_type > MXT_MAX_OBJECT_TYPES) { /* Unknown object type */ dev_err(&client->dev, "maXTouch object type [%d] not recognized\n", object_type); return -ENXIO; } /* Save frequently needed info. */ if (object_type == MXT_GEN_MESSAGEPROCESSOR_T5) { mxt->msg_proc_addr = object_address; /*mxt->message_size = object_size;*/ /*note: changed message_length to 8 in ver0.9*/ mxt->message_size = MXT_MESSAGE_LENGTH; } 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; object_info_address += MXT_OBJECT_TABLE_ELEMENT_SIZE; } 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) { pr_err("maXTouch: Can't allocate memory!\n"); return -ENOMEM; } mxt->last_message = kzalloc(mxt->message_size, GFP_KERNEL); if (mxt->last_message == NULL) { pr_err("maXTouch: Can't allocate memory!\n"); return -ENOMEM; } 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); return -ENXIO; } /* 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++; } } } /* 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"); } crc = (buf[2] << 16) | (buf[1] << 8) | buf[0]; if (calculate_infoblock_crc(mxt, &crc_calculated) < 0) printk(KERN_DEBUG "[TSP] Error while calculating CRC!\n"); if (debug >= DEBUG_TRACE) { printk(KERN_DEBUG "[TSP] Reported info block CRC = 0x%6X\n\n", crc); printk(KERN_DEBUG "[TSP] Calculated info block CRC = 0x%6X\n\n", crc_calculated); } if (crc == crc_calculated) { mxt->info_block_crc = crc; } else { mxt->info_block_crc = 0; pr_err("maXTouch: info block CRC invalid!\n"); } mxt->delta = NULL; mxt->reference = NULL; mxt->cte = NULL; 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, object_type_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); } } return 0; } u8 mxt_valid_interrupt(void) { return 1; } #ifdef CONFIG_HAS_EARLYSUSPEND static void mxt_early_suspend(struct early_suspend *h) { #ifndef MXT_SLEEP_POWEROFF u8 cmd_sleep[2] = {0}; u16 addr; #endif struct mxt_data *mxt = container_of(h, struct mxt_data, early_suspend); printk(KERN_DEBUG "[TSP] %s has been called!\n", __func__); #if defined(MXT_FACTORY_TEST) /*start firmware updating : not yet finished*/ while (mxt->firm_status_data == 1) { printk(KERN_DEBUG "[TSP] mxt firmware is Downloading : mxt suspend must be delayed!"); msleep(1000); } #endif disable_irq(mxt->client->irq); mxt->enabled = false; /* cancel and wait for all works to stop so they don't try to * communicate with the controller after we turn it off */ #ifdef MXT_CALIBRATE_WORKAROUND cancel_delayed_work_sync(&mxt->calibrate_dwork); #endif cancel_work_sync(&mxt->ta_work); #ifdef MXT_SLEEP_POWEROFF if (mxt->pdata->suspend_platform_hw != NULL) mxt->pdata->suspend_platform_hw(); #else /* * a setting of zeros to IDLEACQINT and ACTVACQINT * forces the chip set to enter Deep Sleep mode. */ addr = get_object_address(MXT_GEN_POWERCONFIG_T7, 0, mxt->object_table, mxt->device_info.num_objs); printk(KERN_DEBUG "[TSP] addr: 0x%02x, buf[0]=0x%x, buf[1]=0x%x", addr, cmd_sleep[0], cmd_sleep[1]); mxt_write_block(mxt->client, addr, 2, (u8 *)cmd_sleep); #endif mxt_forced_release(mxt); } static void mxt_late_resume(struct early_suspend *h) { #ifndef MXT_SLEEP_POWEROFF int cnt; #endif struct mxt_data *mxt = container_of(h, struct mxt_data, early_suspend); printk(KERN_DEBUG "[TSP] %s has been called!\n", __func__); #ifdef MXT_SLEEP_POWEROFF if (mxt->pdata->resume_platform_hw != NULL) mxt->pdata->resume_platform_hw(); #else for (cnt = 10; cnt > 0; cnt--) { if (mxt_power_config(mxt) < 0) continue; if (reset_chip(mxt, RESET_TO_NORMAL) == 0)/* soft reset*/ break; } if (cnt == 0) pr_err("%s : reset_chip failed!!!\n", __func__); /*typical atmel spec. value is 250ms, but it sometimes fails to recover so it needs more*/ msleep(300); #endif mxt->pdata->fherr_cnt = 0; mxt->pdata->fherr_cnt_no_ta = 0; if (!work_pending(&mxt->ta_work)) schedule_work(&mxt->ta_work); mxt->enabled = true; enable_irq(mxt->client->irq); #ifdef MXT_CALIBRATE_WORKAROUND schedule_delayed_work(&mxt->calibrate_dwork, msecs_to_jiffies(4000)); #endif } #endif static int __devinit mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct mxt_data *mxt; struct mxt_platform_data *pdata; struct input_dev *input; struct device *tsp_dev; int error; int i; error = 0xff; if (debug >= DEBUG_INFO) { printk(KERN_DEBUG "[TSP] maXTouch driver\n"); printk(KERN_DEBUG "[TSP] \t \"%s\"\n", client->name); printk(KERN_DEBUG "[TSP] \taddr:\t0x%04x\n", client->addr); printk(KERN_DEBUG "[TSP] \tirq:\t%d\n", client->irq); printk(KERN_DEBUG "[TSP] \tflags:\t0x%04x\n", client->flags); printk(KERN_DEBUG "[TSP] \tadapter:\"%s\"\n", client->adapter->name); printk(KERN_DEBUG "[TSP] \tdevice:\t\"%s\"\n", client->dev.init_name); } /* Allocate structure - we need it to identify device */ mxt = kzalloc(sizeof(struct mxt_data), GFP_KERNEL); if (!mxt) { dev_err(&client->dev, "insufficient memory\n"); error = -ENOMEM; goto err_mxt_alloc; } input = input_allocate_device(); if (!input) { dev_err(&client->dev, "error allocating input device\n"); error = -ENOMEM; goto err_input_dev_alloc; } /* Initialize Platform data */ pdata = client->dev.platform_data; if (pdata == NULL) { dev_err(&client->dev, "platform data is required!\n"); goto err_pdata; } mxt->pdata = pdata; mxt->client = client; mxt->input = input; #if defined(MXT_FACTORY_TEST) mxt->firm_status_data = 0; mxt->firm_normal_status_ack = 0; #endif mxt->read_fail_counter = 0; mxt->message_counter = 0; mxt->bytes_to_read = 0; msleep(200); if (mxt_identify(client, mxt)) { dev_err(&client->dev, "Chip could not be identified\n"); goto err_identify; } if (mxt_read_object_table(client, mxt)) { dev_err(&client->dev, "failed to read object table\n"); goto err_read_ot; } INIT_WORK(&mxt->ta_work, mxt_ta_worker); INIT_WORK(&mxt->fhe_work, mxt_fhe_worker); #ifdef MXT_FACTORY_TEST INIT_DELAYED_WORK(&mxt->firmup_dwork, set_mxt_update_exe); #endif #ifdef MXT_CALIBRATE_WORKAROUND INIT_DELAYED_WORK(&mxt->calibrate_dwork, mxt_calibrate_worker); #endif #ifdef CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK INIT_DELAYED_WORK(&mxt->dvfs_dwork, free_dvfs_lock); mxt->dvfs_lock_status = false; #endif /* Register callbacks */ /* To inform tsp , charger connection status*/ mxt->callbacks.inform_charger = mxt_inform_charger_connection; if (mxt->pdata->register_cb) mxt->pdata->register_cb(&mxt->callbacks); init_waitqueue_head(&mxt->msg_queue); mutex_init(&mxt->mutex); spin_lock_init(&mxt->lock); wake_lock_init(&mxt->wakelock, WAKE_LOCK_SUSPEND, "touch"); snprintf( mxt->phys_name, sizeof(mxt->phys_name), "%s/input0", dev_name(&client->dev) ); input->name = client->driver->driver.name; input->phys = mxt->phys_name; input->id.bustype = BUS_I2C; input->dev.parent = &client->dev; if (debug >= DEBUG_INFO) { printk(KERN_DEBUG "[TSP] maXTouch name: \"%s\"\n", input->name); printk(KERN_DEBUG "[TSP] maXTouch phys: \"%s\"\n", input->phys); printk(KERN_DEBUG "[TSP] maXTouch driver setting abs parameters\n"); } __set_bit(EV_ABS, input->evbit); __set_bit(EV_KEY, input->evbit); __set_bit(MT_TOOL_FINGER, input->keybit); __set_bit(INPUT_PROP_DIRECT, input->propbit); input_mt_init_slots(input, MXT_MAX_NUM_TOUCHES); input_set_abs_params(input, ABS_MT_POSITION_X, 0, mxt->pdata->max_x - 1, 0, 0); input_set_abs_params(input, ABS_MT_POSITION_Y, 0, mxt->pdata->max_y - 1, 0, 0); input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); input_set_abs_params(input, ABS_MT_WIDTH_MAJOR, 0, 30, 0, 0); i2c_set_clientdata(client, mxt); input_set_drvdata(input, mxt); error = input_register_device(mxt->input); if (error < 0) { dev_err(&client->dev, "Failed to register input device\n"); goto err_register_device; } #ifndef MXT_TUNNING_ENABLE /* pre-set configuration before soft reset */ error = mxt_config_settings(mxt); if (error < 0) goto err_after_read_ot; #endif for (i = 0; i < MXT_MAX_NUM_TOUCHES ; i++) mxt->mtouch_info[i].status = TSP_STATE_INACTIVE; /* Allocate the interrupt */ mxt->irq = client->irq; mxt->valid_irq_counter = 0; mxt->invalid_irq_counter = 0; mxt->irq_counter = 0; error = request_threaded_irq(mxt->irq, NULL, mxt_threaded_irq, IRQF_TRIGGER_LOW | IRQF_ONESHOT, client->dev.driver->name, mxt); if (error < 0) { dev_err(&client->dev, "failed to allocate irq %d\n", mxt->irq); goto err_irq; } #ifdef CONFIG_HAS_EARLYSUSPEND mxt->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; mxt->early_suspend.suspend = mxt_early_suspend; mxt->early_suspend.resume = mxt_late_resume; register_early_suspend(&mxt->early_suspend); #endif /* CONFIG_HAS_EARLYSUSPEND */ tsp_dev = device_create(sec_class, NULL, 0, mxt, "sec_touchscreen"); if (IS_ERR(tsp_dev)) { pr_err("Failed to create device for the sysfs\n"); error = -ENODEV; goto err_sysfs_create_group; } error = sysfs_create_group(&tsp_dev->kobj, &maxtouch_attr_group); if (error) { pr_err("Failed to create sysfs group\n"); goto err_sysfs_create_group; } #ifdef ITDEV error = sysfs_create_group(&client->dev.kobj, &libmaxtouch_attr_group); if (error) { pr_err("Failed to create libmaxtouch sysfs group\n"); goto err_sysfs_create_group; } sysfs_bin_attr_init(&mem_access_attr); mem_access_attr.attr.name = "mem_access"; mem_access_attr.attr.mode = S_IRUGO | S_IWUGO; mem_access_attr.read = mem_access_read; mem_access_attr.write = mem_access_write; mem_access_attr.size = 65535; if (sysfs_create_bin_file(&client->dev.kobj, &mem_access_attr) < 0) { pr_err("Failed to create device file(%s)!\n", mem_access_attr.attr.name); goto err_sysfs_create_group; } #endif #ifdef MXT_CALIBRATE_WORKAROUND schedule_delayed_work(&mxt->calibrate_dwork, 10 * HZ); #endif mxt->enabled = true; return 0; err_sysfs_create_group: #ifdef CONFIG_HAS_EARLYSUSPEND unregister_early_suspend(&mxt->early_suspend); #endif if (mxt->irq) free_irq(mxt->irq, mxt); err_irq: err_after_read_ot: if (mxt != NULL) { kfree(mxt->rid_map); kfree(mxt->delta); kfree(mxt->reference); kfree(mxt->cte); kfree(mxt->object_table); kfree(mxt->last_message); } input_unregister_device(mxt->input); input = NULL; err_register_device: cancel_work_sync(&mxt->ta_work); #ifdef MXT_CALIBRATE_WORKAROUND cancel_delayed_work_sync(&mxt->calibrate_dwork); #endif err_read_ot: err_identify: err_pdata: if (input) input_free_device(input); err_input_dev_alloc: if (mxt->pdata->exit_platform_hw != NULL) mxt->pdata->exit_platform_hw(); kfree(mxt); err_mxt_alloc: return error; } static int __devexit mxt_remove(struct i2c_client *client) { struct mxt_data *mxt; mxt = i2c_get_clientdata(client); /* Close down sysfs entries */ sysfs_remove_group(&client->dev.kobj, &maxtouch_attr_group); #ifdef CONFIG_HAS_EARLYSUSPEND wake_lock_destroy(&mxt->wakelock); unregister_early_suspend(&mxt->early_suspend); #endif /* CONFIG_HAS_EARLYSUSPEND */ /* Release IRQ so no queue will be scheduled */ if (mxt->irq) free_irq(mxt->irq, mxt); /* Should dealloc deltas, references, CTE structures, if allocated */ if (mxt != NULL) { kfree(mxt->rid_map); kfree(mxt->delta); kfree(mxt->reference); kfree(mxt->cte); kfree(mxt->object_table); kfree(mxt->last_message); } input_unregister_device(mxt->input); cancel_work_sync(&mxt->ta_work); #ifdef MXT_CALIBRATE_WORKAROUND cancel_delayed_work_sync(&mxt->calibrate_dwork); #endif if (mxt->pdata->exit_platform_hw != NULL) mxt->pdata->exit_platform_hw(); kfree(mxt); i2c_set_clientdata(client, NULL); if (debug >= DEBUG_TRACE) dev_info(&client->dev, "Touchscreen unregistered\n"); return 0; } #if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND) static int mxt_suspend(struct i2c_client *client, pm_message_t mesg) { struct mxt_data *mxt = i2c_get_clientdata(client); if (device_may_wakeup(&client->dev)) enable_irq_wake(mxt->irq); return 0; } static int mxt_resume(struct i2c_client *client) { struct mxt_data *mxt = i2c_get_clientdata(client); if (device_may_wakeup(&client->dev)) disable_irq_wake(mxt->irq); return 0; } #else #define mxt_suspend NULL #define mxt_resume NULL #endif static const struct i2c_device_id mxt_idtable[] = { {"sec_touchscreen", 0,}, { } }; MODULE_DEVICE_TABLE(i2c, mxt_idtable); static struct i2c_driver mxt_driver = { .driver = { .name = "sec_touchscreen", .owner = THIS_MODULE, }, .id_table = mxt_idtable, .probe = mxt_probe, .remove = __devexit_p(mxt_remove), .suspend = mxt_suspend, .resume = mxt_resume, }; static int __init mxt_init(void) { return i2c_add_driver(&mxt_driver); } static void __exit mxt_cleanup(void) { i2c_del_driver(&mxt_driver); } module_init(mxt_init); module_exit(mxt_cleanup); MODULE_AUTHOR("Samsung"); MODULE_DESCRIPTION("Driver for Atmel mXT1386 Touchscreen Controller"); MODULE_LICENSE("GPL");