/drivers/input/touchscreen/mxt1664s.c
C | 3402 lines | 2702 code | 519 blank | 181 comment | 459 complexity | 25c51b4c04a5187fb284aa0ce1357ade MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
Large files files are truncated, but you can click here to view the full file
- /*
- * Copyright (C) 2010, Samsung Electronics Co. Ltd. All Rights Reserved.
- *
- * 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.
- *
- */
- #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/input.h>
- #include <linux/input/mt.h>
- #include <linux/interrupt.h>
- #include <linux/i2c.h>
- #include <linux/delay.h>
- #include <linux/earlysuspend.h>
- #include <linux/slab.h>
- #include <linux/gpio.h>
- #include <linux/i2c/mxt1664s.h>
- #include <asm/unaligned.h>
- #include <linux/firmware.h>
- #include <linux/string.h>
- #define OBJECT_TABLE_START_ADDRESS 7
- #define OBJECT_TABLE_ELEMENT_SIZE 6
- #define CMD_RESET_OFFSET 0
- #define CMD_BACKUP_OFFSET 1
- #define CMD_CALIBRATE_OFFSET 2
- #define CMD_REPORTATLL_OFFSET 3
- #define CMD_DEBUG_CTRL_OFFSET 4
- #define CMD_DIAGNOSTIC_OFFSET 5
- #define DETECT_MSG_MASK 0x80
- #define PRESS_MSG_MASK 0x40
- #define RELEASE_MSG_MASK 0x20
- #define MOVE_MSG_MASK 0x10
- #define AMPLITUDE_MSG_MASK 0x04
- #define SUPPRESS_MSG_MASK 0x02
- /* Slave addresses */
- /* need to check + */
- #define MXT_APP_LOW 0x4a
- #define MXT_APP_HIGH 0x4d
- #define MXT_BOOT_LOW 0x26
- #define MXT_BOOT_HIGH 0x27
- /* need to check - */
- /* FIRMWARE NAME */
- #define MXT_FW_NAME "tsp_atmel/mXT1664S.fw"
- #define MXT_BOOT_VALUE 0xa5
- #define MXT_BACKUP_VALUE 0x55
- /* 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
- /* Command to unlock bootloader */
- #define MXT_UNLOCK_CMD_MSB 0xaa
- #define MXT_UNLOCK_CMD_LSB 0xdc
- #define ID_BLOCK_SIZE 7
- #define MXT_STATE_INACTIVE -1
- #define MXT_STATE_RELEASE 0
- #define MXT_STATE_PRESS 1
- #define MXT_STATE_MOVE 2
- #define MAX_USING_FINGER_NUM 10
- /* Feature */
- /*#######################################*/
- #define TOUCH_BOOSTER 1
- #define USE_SUMSIZE 0
- #define SYSFS 1
- #define FOR_BRINGUP 1
- #define UPDATE_ON_PROBE 1
- #define READ_FW_FROM_HEADER 0
- #define FOR_DEBUGGING_TEST_DOWNLOADFW_BIN 0
- #define ITDEV 1
- #define SHOW_COORDINATE 1
- #define DEBUG_INFO 0
- /*#######################################*/
- /* touch booster */
- #if TOUCH_BOOSTER
- #include <mach/cpufreq.h>
- #define TOUCH_BOOSTER_TIME 3000
- #define TOUCH_BOOSTER_LIMIT_CLK 500000
- static bool tsp_press_status;
- static bool touch_cpu_lock_status;
- static int cpu_lv = -1;
- #endif
- /* use sumsize in T57 register */
- #if USE_SUMSIZE
- #define MAX_SUMSIZE 40
- #define MAX_SINGLE_SUMSIZE 100
- static uint16_t sum_size;
- #endif
- /* Firmware */
- #if READ_FW_FROM_HEADER
- static u8 firmware_mXT[] = {
- #include "mXT1664S-V0.5.2_.h"
- };
- #endif
- #if ITDEV
- static int driver_paused;
- static int debug_enabled;
- #endif
- /* add for protection code */
- /*#######################################*/
- /*#######################################*/
- /* variable related protection code */
- /*#######################################*/
- static int treat_median_error_status;
- /*#######################################*/
- struct object_t {
- u8 object_type;
- u16 i2c_address;
- u8 size;
- u8 instances;
- u8 num_report_ids;
- } __packed;
- struct finger_info {
- s16 x;
- s16 y;
- s16 z;
- u16 w;
- s8 state;
- int16_t component;
- u16 mcount; /*add for debug*/
- };
- struct report_id_map_t {
- u8 object_type; /*!< Object type. */
- u8 instance; /*!< Instance number. */
- };
- u8 max_report_id;
- struct report_id_map_t *rid_map;
- static bool rid_map_alloc;
- struct mxt_data {
- struct i2c_client *client;
- struct input_dev *input_dev;
- struct mxt_platform_data *pdata;
- struct early_suspend early_suspend;
- u8 family_id;
- u32 finger_mask;
- int gpio_read_done;
- struct object_t *objects;
- u8 objects_len;
- u8 tsp_version;
- u8 tsp_build;
- u8 tsp_variant;
- u8 finger_type;
- u16 msg_proc;
- u16 cmd_proc;
- u16 msg_object_size;
- u32 x_dropbits:2;
- u32 y_dropbits:2;
- u8 tchthr_batt;
- u8 tchthr_charging;
- u8 calcfg_batt;
- u8 calcfg_charging;
- const u8 *t48_config_batt;
- const u8 *t48_config_chrg;
- #if TOUCH_BOOSTER
- struct delayed_work dvfs_dwork;
- #endif
- void (*power_on)(void);
- void (*power_off)(void);
- void (*register_cb)(void *);
- void (*read_ta_status)(bool *);
- int num_fingers;
- #if ITDEV
- u16 last_read_addr;
- u16 msg_proc_addr;
- #endif
- struct finger_info fingers[];
- };
- struct mxt_data *copy_data;
- int touch_is_pressed;
- EXPORT_SYMBOL(touch_is_pressed);
- static int mxt_enabled;
- static bool g_debug_switch;
- static u8 threshold;
- static int firm_status_data;
- static u8 firmware_latest[] = {0x5, 0x2}; /* version, build_version */
- #if DEBUG_INFO
- static u8 *object_type_name[60] = {
- /* [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_COMCONFIG_T18",
- /* [22] = "PROCG_NOISESUPPRESSION_T22",*/
- /* [23] = "TOUCH_PROXIMITY_T23",*/
- /* [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",
- [42] = "PROCI_TOUCHSUPPRESSION_T42",
- [43] = "SPT_DIGITIZER_T43",
- [46] = "SPT_CTECONFIG_T46",
- [48] = "PROCG_NOISESUPPRESSION_T48",
- [56] = "PROCI_SHIELDLESS_T56",
- [57] = "SPT_GENERICDATA_T57",
- };
- #endif
- /* declare function proto type */
- static void mxt_ta_probe(int ta_status);
- static void report_input_data(struct mxt_data *data);
- static int read_mem(struct mxt_data *data, u16 reg, u8 len, u8 *buf)
- {
- int ret;
- u16 le_reg = cpu_to_le16(reg);
- struct i2c_msg msg[2] = {
- {
- .addr = data->client->addr,
- .flags = 0,
- .len = 2,
- .buf = (u8 *)&le_reg,
- },
- {
- .addr = data->client->addr,
- .flags = I2C_M_RD,
- .len = len,
- .buf = buf,
- },
- };
- ret = i2c_transfer(data->client->adapter, msg, 2);
- if (ret < 0) {
- pr_err("i2c failed ret = %d\n", ret);
- return ret;
- }
- return ret == 2 ? 0 : -EIO;
- }
- static int write_mem(struct mxt_data *data, u16 reg, u8 len, const u8 *buf)
- {
- int ret;
- u8 tmp[len + 2];
- put_unaligned_le16(cpu_to_le16(reg), tmp);
- memcpy(tmp + 2, buf, len);
- ret = i2c_master_send(data->client, tmp, sizeof(tmp));
- if (ret < 0)
- return ret;
- return ret == sizeof(tmp) ? 0 : -EIO;
- }
- static int __devinit mxt_reset(struct mxt_data *data)
- {
- u8 buf = 1u;
- return write_mem(data, data->cmd_proc + CMD_RESET_OFFSET, 1, &buf);
- }
- static int __devinit mxt_backup(struct mxt_data *data)
- {
- u8 buf = 0x55u;
- return write_mem(data, data->cmd_proc + CMD_BACKUP_OFFSET, 1, &buf);
- }
- static int get_object_info(struct mxt_data *data, u8 object_type, u16 *size,
- u16 *address)
- {
- int i;
- for (i = 0; i < data->objects_len; i++) {
- if (data->objects[i].object_type == object_type) {
- *size = data->objects[i].size + 1;
- *address = data->objects[i].i2c_address;
- return 0;
- }
- }
- return -ENODEV;
- }
- static int write_config(struct mxt_data *data, u8 type, const u8 *cfg)
- {
- int ret;
- u16 address = 0;
- u16 size = 0;
- ret = get_object_info(data, type, &size, &address);
- if (size == 0 && address == 0)
- return 0;
- else
- return write_mem(data, address, size, cfg);
- }
- static int check_instance(struct mxt_data *data, u8 object_type)
- {
- int i;
- for (i = 0; i < data->objects_len; i++) {
- if (data->objects[i].object_type == object_type)
- return data->objects[i].instances;
- }
- return 0;
- }
- static int init_write_config(struct mxt_data *data, u8 type, const u8 *cfg)
- {
- int ret;
- u16 address = 0;
- u16 size = 0;
- u8 *temp;
- ret = get_object_info(data, type, &size, &address);
- if ((size == 0) || (address == 0)) {
- pr_err("%s error object_type(%d)\n", __func__, type);
- return -ENODEV;
- }
- ret = write_mem(data, address, size, cfg);
- if (check_instance(data, type)) {
- #if DEBUG_INFO
- pr_info("exist instance1 object (%d)\n", type);
- #endif
- temp = kmalloc(size * sizeof(u8), GFP_KERNEL);
- memset(temp, 0, size);
- ret |= write_mem(data, address+size, size, temp);
- kfree(temp);
- }
- return ret;
- }
- static int change_config(struct mxt_data *data,
- u16 reg, u8 offeset, u8 change_value)
- {
- u8 value = 0;
- value = change_value;
- return write_mem(data, reg+offeset, 1, &value);
- }
- static u32 __devinit crc24(u32 crc, u8 byte1, u8 byte2)
- {
- static const u32 crcpoly = 0x80001B;
- u32 res;
- u16 data_word;
- data_word = (((u16)byte2) << 8) | byte1;
- res = (crc << 1) ^ (u32)data_word;
- if (res & 0x1000000)
- res ^= crcpoly;
- return res;
- }
- static int __devinit calculate_infoblock_crc(struct mxt_data *data,
- u32 *crc_pointer)
- {
- u32 crc = 0;
- u8 mem[7 + data->objects_len * 6];
- int status;
- int i;
- status = read_mem(data, 0, sizeof(mem), mem);
- if (status)
- return status;
- for (i = 0; i < sizeof(mem) - 1; i += 2)
- crc = crc24(crc, mem[i], mem[i + 1]);
- *crc_pointer = crc24(crc, mem[i], 0) & 0x00FFFFFF;
- return 0;
- }
- uint8_t calibrate_chip_e(void)
- {
- u8 cal_data = 1;
- int ret = 0;
- /* send calibration command to the chip */
- ret = write_mem(copy_data,
- copy_data->cmd_proc + CMD_CALIBRATE_OFFSET,
- 1, &cal_data);
- /* set flag for calibration lockup
- recovery if cal command was successful */
- if (!ret)
- pr_info("calibration success!!!\n");
- return ret;
- }
- static void treat_error_status(void)
- {
- bool ta_status = 0;
- u16 size;
- u16 obj_address = 0;
- int error = 0;
- struct mxt_data *data = copy_data;
- data->read_ta_status(&ta_status);
- if (treat_median_error_status) {
- pr_err("Error status already treated\n");
- return;
- } else
- treat_median_error_status = 1;
- pr_info("Error status TA is[%d]\n", ta_status);
- if (ta_status) {
- #if !(FOR_BRINGUP)
- get_object_info(data,
- GEN_POWERCONFIG_T7, &size, &obj_address);
- /* 1:ACTVACQINT */
- error = change_config(data, obj_address, 1, 255);
- get_object_info(data,
- GEN_ACQUISITIONCONFIG_T8, &size, &obj_address);
- /* 0:CHRGTIME */
- error |= change_config(data, obj_address, 0, 64);
- /* 8:ATCHFRCCALTHR*/
- error |= change_config(data, obj_address, 8, 50);
- /* 9:ATCHFRCCALRATIO*/
- error |= change_config(data, obj_address, 9, 0);
- get_object_info(data,
- PROCI_TOUCHSUPPRESSION_T42, &size, &obj_address);
- /* 0:CTRL */
- error |= change_config(data, obj_address, 0, 3);
- get_object_info(data,
- SPT_CTECONFIG_T46, &size, &obj_address);
- /* 2:IDLESYNCSPERX */
- error |= change_config(data, obj_address, 2, 48);
- /* 3:ACTVSYNCSPERX */
- error |= change_config(data, obj_address, 3, 48);
- get_object_info(data,
- PROCG_NOISESUPPRESSION_T48, &size, &obj_address);
- /* 2:CALCFG */
- error |= change_config(data, obj_address, 2, 114);
- /* 3:BASEFREQ */
- error |= change_config(data, obj_address, 3, 15);
- /* 8:MFFREQ[0] */
- error |= change_config(data, obj_address, 8, 3);
- /* 9:MFFREQ[1] */
- error |= change_config(data, obj_address, 9, 5);
- /* 10:NLGAIN*/
- error |= change_config(data, obj_address, 10, 96);
- /* 11:NLTHR*/
- error |= change_config(data, obj_address, 11, 30);
- /* 17:GCMAXADCSPERX */
- error |= change_config(data, obj_address, 17, 100);
- /* 34:BLEN[0] */
- error |= change_config(data, obj_address, 34, 80);
- /* 35:TCHTHR[0] */
- error |= change_config(data, obj_address, 35, 40);
- /* 36:TCHDI[0] */
- error |= change_config(data, obj_address, 36, 2);
- /* 39:MOVFILTER[0] */
- error |= change_config(data, obj_address, 39, 65);
- /* 41:MRGHYST[0] */
- error |= change_config(data, obj_address, 41, 40);
- /* 42:MRGTHR[0] */
- error |= change_config(data, obj_address, 42, 50);
- /* 43:XLOCLIP[0] */
- error |= change_config(data, obj_address, 43, 5);
- /* 44:XHICLIP[0] */
- error |= change_config(data, obj_address, 44, 5);
- /* 51:JUMPLIMIT[0] */
- error |= change_config(data, obj_address, 51, 25);
- /* 52:TCHHYST[0] */
- error |= change_config(data, obj_address, 52, 15);
- #endif
- if (error < 0)
- pr_err("failed to write error status\n");
- } else {
- #if !(FOR_BRINGUP)
- get_object_info(data,
- GEN_POWERCONFIG_T7, &size, &obj_address);
- /* 1:ACTVACQINT */
- error = change_config(data, obj_address, 1, 255);
- get_object_info(data,
- GEN_ACQUISITIONCONFIG_T8, &size, &obj_address);
- /* 0:CHRGTIME */
- error |= change_config(data, obj_address, 0, 64);
- /* 8:ATCHFRCCALTHR*/
- error |= change_config(data, obj_address, 8, 50);
- /* 9:ATCHFRCCALRATIO*/
- error |= change_config(data, obj_address, 9, 0);
- get_object_info(data,
- TOUCH_MULTITOUCHSCREEN_T9, &size, &obj_address);
- /* 31:TCHHYST */
- error |= change_config(data, obj_address, 31, 15);
- get_object_info(data,
- PROCI_TOUCHSUPPRESSION_T42, &size, &obj_address);
- /* 0:CTRL */
- error |= change_config(data, obj_address, 0, 3);
- get_object_info(data,
- SPT_CTECONFIG_T46, &size, &obj_address);
- /* 2:IDLESYNCSPERX */
- error |= change_config(data, obj_address, 2, 48);
- /* 3:ACTVSYNCSPERX */
- error |= change_config(data, obj_address, 3, 48);
- get_object_info(data,
- PROCG_NOISESUPPRESSION_T48, &size, &obj_address);
- /* 2:CALCFG */
- error |= change_config(data, obj_address, 2, 242);
- /* 3:BASEFREQ */
- error |= change_config(data, obj_address, 3, 15);
- /* 8:MFFREQ[0] */
- error |= change_config(data, obj_address, 8, 3);
- /* 9:MFFREQ[1] */
- error |= change_config(data, obj_address, 9, 5);
- /* 10:NLGAIN*/
- error |= change_config(data, obj_address, 10, 112);
- /* 11:NLTHR*/
- error |= change_config(data, obj_address, 11, 25);
- /* 17:GCMAXADCSPERX */
- error |= change_config(data, obj_address, 17, 100);
- /* 34:BLEN[0] */
- error |= change_config(data, obj_address, 34, 112);
- /* 35:TCHTHR[0] */
- error |= change_config(data, obj_address, 35, 40);
- /* 41:MRGHYST[0] */
- error |= change_config(data, obj_address, 41, 40);
- /* 42:MRGTHR[0] */
- error |= change_config(data, obj_address, 42, 50);
- /* 51:JUMPLIMIT[0] */
- error |= change_config(data, obj_address, 51, 25);
- /* 52:TCHHYST[0] */
- error |= change_config(data, obj_address, 52, 15);
- #endif
- if (error < 0)
- pr_err("failed to write error status\n");
- }
- }
- #if TOUCH_BOOSTER
- static void mxt_set_dvfs_off(struct work_struct *work)
- {
- struct mxt_data *data =
- container_of(work, struct mxt_data, dvfs_dwork.work);
- if (mxt_enabled) {
- disable_irq(data->client->irq);
- if (touch_cpu_lock_status
- && !tsp_press_status){
- exynos_cpufreq_lock_free(DVFS_LOCK_ID_TSP);
- touch_cpu_lock_status = 0;
- }
- enable_irq(data->client->irq);
- }
- }
- static void mxt_set_dvfs_on(struct mxt_data *data)
- {
- cancel_delayed_work(&data->dvfs_dwork);
- if (cpu_lv < 0)
- exynos_cpufreq_get_level(TOUCH_BOOSTER_LIMIT_CLK, &cpu_lv);
- exynos_cpufreq_lock(DVFS_LOCK_ID_TSP, cpu_lv);
- touch_cpu_lock_status = 1;
- }
- #endif
- static void mxt_ta_probe(int ta_status)
- {
- #if !(FOR_BRINGUP)
- u16 obj_address = 0;
- u16 size;
- int error;
- struct mxt_data *data = copy_data;
- if (!mxt_enabled) {
- pr_err("%s mxt_enabled is 0\n", __func__);
- return;
- }
- if (treat_median_error_status)
- treat_median_error_status = 0;
- if (ta_status) {
- error = write_config(data, data->t48_config_chrg[0],
- data->t48_config_chrg + 1);
- threshold = data->tchthr_charging;
- if (error < 0)
- pr_err("ta_probe write config Error!!\n");
- } else {
- error |= write_config(data, data->t48_config_batt[0],
- data->t48_config_batt + 1);
- threshold = data->tchthr_batt;
- if (error < 0)
- pr_err("%s write config Error!!\n", __func__);
- }
- #endif
- pr_info("%s : threshold[%d]\n", __func__, threshold);
- };
- uint8_t reportid_to_type(struct mxt_data *data, u8 report_id, u8 *instance)
- {
- struct report_id_map_t *report_id_map;
- report_id_map = rid_map;
- if (report_id <= max_report_id) {
- *instance = report_id_map[report_id].instance;
- return report_id_map[report_id].object_type;
- } else
- return 0;
- }
- static int __devinit mxt_init_touch_driver(struct mxt_data *data)
- {
- struct object_t *object_table;
- struct report_id_map_t *report_id_map_t;
- u32 read_crc = 0;
- u32 calc_crc;
- u16 crc_address;
- u16 dummy;
- int i, j;
- u8 id[ID_BLOCK_SIZE];
- int ret;
- u8 type_count = 0;
- u8 tmp;
- int current_report_id, start_report_id;
- ret = read_mem(data, 0, sizeof(id), id);
- if (ret)
- return ret;
- pr_info("family = %#02x, variant = %#02x, version "
- "= %#02x, build = %#02x, "
- "matrix X,Y size = %d,%d\n"
- , id[0], id[1], id[2], id[3], id[4], id[5]);
- data->family_id = id[0];
- data->tsp_variant = id[1];
- data->tsp_version = id[2];
- data->tsp_build = id[3];
- data->objects_len = id[6];
- object_table = kmalloc(data->objects_len * sizeof(*object_table),
- GFP_KERNEL);
- if (!object_table)
- return -ENOMEM;
- ret = read_mem(data, OBJECT_TABLE_START_ADDRESS,
- data->objects_len * sizeof(*object_table),
- (u8 *)object_table);
- if (ret)
- goto err;
- max_report_id = 0;
- for (i = 0; i < data->objects_len; i++) {
- object_table[i].i2c_address =
- le16_to_cpu(object_table[i].i2c_address);
- max_report_id += object_table[i].num_report_ids *
- (object_table[i].instances + 1);
- tmp = 0;
- if (object_table[i].num_report_ids) {
- tmp = type_count + 1;
- type_count += object_table[i].num_report_ids *
- (object_table[i].instances + 1);
- }
- switch (object_table[i].object_type) {
- case TOUCH_MULTITOUCHSCREEN_T9:
- data->finger_type = tmp;
- pr_info("Finger type = %d\n",
- data->finger_type);
- break;
- case GEN_MESSAGEPROCESSOR_T5:
- #if ITDEV
- data->msg_proc_addr = object_table[i].i2c_address;
- #endif
- data->msg_object_size = object_table[i].size + 1;
- break;
- }
- }
- if (rid_map_alloc) {
- rid_map_alloc = false;
- kfree(rid_map);
- }
- rid_map = kmalloc((sizeof(report_id_map_t) * max_report_id + 1),
- GFP_KERNEL);
- if (!rid_map) {
- kfree(object_table);
- return -ENOMEM;
- }
- rid_map_alloc = true;
- rid_map[0].instance = 0;
- rid_map[0].object_type = 0;
- current_report_id = 1;
- for (i = 0; i < data->objects_len; i++) {
- if (object_table[i].num_report_ids != 0) {
- for (j = 0; j <= object_table[i].instances; j++) {
- for (start_report_id = current_report_id;
- current_report_id <
- (start_report_id +
- object_table[i].num_report_ids);
- current_report_id++) {
- rid_map[current_report_id].instance = j;
- rid_map[current_report_id].object_type =
- object_table[i].object_type;
- }
- }
- }
- }
- data->objects = object_table;
- /* Verify CRC */
- crc_address = OBJECT_TABLE_START_ADDRESS +
- data->objects_len * OBJECT_TABLE_ELEMENT_SIZE;
- #ifdef __BIG_ENDIAN
- #error The following code will likely break on a big endian machine
- #endif
- ret = read_mem(data, crc_address, 3, (u8 *)&read_crc);
- if (ret)
- goto err;
- read_crc = le32_to_cpu(read_crc);
- ret = calculate_infoblock_crc(data, &calc_crc);
- if (ret)
- goto err;
- if (read_crc != calc_crc) {
- pr_err("CRC error\n");
- ret = -EFAULT;
- goto err;
- }
- ret = get_object_info(data, GEN_MESSAGEPROCESSOR_T5, &dummy,
- &data->msg_proc);
- if (ret)
- goto err;
- ret = get_object_info(data, GEN_COMMANDPROCESSOR_T6, &dummy,
- &data->cmd_proc);
- if (ret)
- goto err;
- #if DEBUG_INFO
- pr_info("maXTouch: %d Objects\n",
- data->objects_len);
- for (i = 0; i < data->objects_len; i++) {
- pr_info("Type:\t\t\t[%d]: %s\n",
- object_table[i].object_type,
- object_type_name[object_table[i].object_type]);
- pr_info("\tAddress:\t0x%04X\n",
- object_table[i].i2c_address);
- pr_info("\tSize:\t\t%d Bytes\n",
- object_table[i].size);
- pr_info("\tInstances:\t%d\n",
- object_table[i].instances);
- pr_info("\tReport Id's:\t%d\n",
- object_table[i].num_report_ids);
- }
- #endif
- return 0;
- err:
- kfree(object_table);
- return ret;
- }
- static void report_input_data(struct mxt_data *data)
- {
- int i;
- int count = 0;
- int report_count = 0;
- for (i = 0; i < data->num_fingers; i++) {
- if (data->fingers[i].state == MXT_STATE_INACTIVE)
- continue;
- if (data->fingers[i].state == MXT_STATE_RELEASE) {
- input_mt_slot(data->input_dev, i);
- input_mt_report_slot_state(data->input_dev,
- MT_TOOL_FINGER, false);
- } else {
- input_mt_slot(data->input_dev, i);
- input_mt_report_slot_state(data->input_dev,
- MT_TOOL_FINGER, true);
- input_report_abs(data->input_dev, ABS_MT_POSITION_X,
- data->fingers[i].x);
- input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
- data->fingers[i].y);
- input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
- data->fingers[i].z);
- input_report_abs(data->input_dev, ABS_MT_PRESSURE,
- data->fingers[i].w);
- }
- #ifdef _SUPPORT_SHAPE_TOUCH_
- input_report_abs(data->input_dev, ABS_MT_COMPONENT,
- data->fingers[i].component);
- #endif
- report_count++;
- #if SHOW_COORDINATE
- switch (data->fingers[i].state) {
- case MXT_STATE_PRESS:
- pr_info("P: "
- "id[%d],x=%d,y=%d,w=%d\n",
- i, data->fingers[i].x, data->fingers[i].y
- , data->fingers[i].w);
- break;
- /*
- case MXT_STATE_MOVE:
- pr_info("M: "
- "id[%d],x=%d,y=%d,w=%d,mc=%d\n",
- i, data->fingers[i].x, data->fingers[i].y
- , data->fingers[i].w, data->fingers[i].mcount);
- break;
- */
- case MXT_STATE_RELEASE:
- pr_info("R: "
- "id[%d],mc=%d\n",
- i, data->fingers[i].mcount);
- break;
- default:
- break;
- }
- #else
- if (data->fingers[i].state == MXT_STATE_PRESS)
- pr_info("P: id[%d],w=%d\n"
- , i, data->fingers[i].w);
- else if (data->fingers[i].state == MXT_STATE_RELEASE)
- pr_info("R: id[%d],mc=%d\n"
- , i, data->fingers[i].mcount);
- #endif
- if (data->fingers[i].state == MXT_STATE_RELEASE) {
- data->fingers[i].state = MXT_STATE_INACTIVE;
- data->fingers[i].mcount = 0;
- } else {
- data->fingers[i].state = MXT_STATE_MOVE;
- count++;
- }
- }
- if (report_count > 0) {
- #if ITDEV
- if (!driver_paused)
- #endif
- input_sync(data->input_dev);
- }
- if (count)
- touch_is_pressed = 1;
- else
- touch_is_pressed = 0;
- #if TOUCH_BOOSTER
- if (count == 0) {
- if (touch_cpu_lock_status) {
- cancel_delayed_work(&data->dvfs_dwork);
- schedule_delayed_work(&data->dvfs_dwork,
- msecs_to_jiffies(TOUCH_BOOSTER_TIME));
- }
- tsp_press_status = 0;
- } else
- tsp_press_status = 1;
- #endif
- data->finger_mask = 0;
- }
- static irqreturn_t mxt_irq_thread(int irq, void *ptr)
- {
- struct mxt_data *data = ptr;
- int id;
- u8 msg[data->msg_object_size];
- u8 touch_message_flag = 0;
- u16 obj_address = 0;
- u16 size;
- u8 value;
- int error;
- u8 object_type, instance;
- do {
- touch_message_flag = 0;
- if (read_mem(data, data->msg_proc, sizeof(msg), msg)) {
- #if TOUCH_BOOSTER
- if (touch_cpu_lock_status) {
- exynos_cpufreq_lock_free(DVFS_LOCK_ID_TSP);
- touch_cpu_lock_status = 0;
- }
- #endif
- return IRQ_HANDLED;
- }
- #if ITDEV
- if (debug_enabled)
- print_hex_dump(KERN_INFO, "MXT MSG:",
- DUMP_PREFIX_NONE, 16, 1, msg, sizeof(msg), false);
- #endif
- object_type = reportid_to_type(data, msg[0] , &instance);
- if (object_type == GEN_COMMANDPROCESSOR_T6) {
- if (msg[1] == 0x00) /* normal mode */
- pr_info("normal mode\n");
- if ((msg[1]&0x04) == 0x04) /* I2C checksum error */
- pr_info("I2C checksum error\n");
- if ((msg[1]&0x08) == 0x08) /* config error */
- pr_info("config error\n");
- if ((msg[1]&0x10) == 0x10) /* calibration */
- pr_info("calibration is"
- " on going !!\n");
- if ((msg[1]&0x20) == 0x20) /* signal error */
- pr_info("signal error\n");
- if ((msg[1]&0x40) == 0x40) /* overflow */
- pr_info("overflow detected\n");
- if ((msg[1]&0x80) == 0x80) /* reset */
- pr_info("reset is ongoing\n");
- }
- if (object_type == PROCI_TOUCHSUPPRESSION_T42) {
- get_object_info(data, GEN_ACQUISITIONCONFIG_T8,
- &size, &obj_address);
- if ((msg[1] & 0x01) == 0x00) {
- /* Palm release */
- pr_info("palm touch released\n");
- touch_is_pressed = 0;
- } else if ((msg[1] & 0x01) == 0x01) {
- /* Palm Press */
- pr_info("palm touch detected\n");
- touch_is_pressed = 1;
- touch_message_flag = 1;
- }
- }
- if (object_type == PROCG_NOISESUPPRESSION_T48) {
- /* pr_info("T48 [STATUS]:%#02x"
- "[ADCSPERX]:%#02x[FRQ]:%#02x"
- "[STATE]:%#02x[NLEVEL]:%#02x\n"
- , msg[1], msg[2], msg[3], msg[4], msg[5]);*/
- if (msg[4] == 5) { /* Median filter error */
- pr_info("Median filter error\n");
- if ((data->family_id == 0xA1)
- && ((data->tsp_version == 0x13)
- || (data->tsp_version == 0x20))) {
- if (data->read_ta_status)
- treat_error_status();
- } else {
- get_object_info(data,
- PROCG_NOISESUPPRESSION_T48,
- &size, &obj_address);
- value = data->calcfg_batt;
- error = write_mem(data,
- obj_address+2, 1, &value);
- msleep(20);
- value |= 0x20;
- error |= write_mem(data,
- obj_address+2, 1, &value);
- if (error)
- pr_err("failed to"
- "reenable CHRGON\n");
- }
- }
- }
- #if USE_SUMSIZE
- if (object_type == SPT_GENERICDATA_T57) {
- sum_size = msg[1];
- sum_size += (msg[2]<<8);
- }
- #endif
- if (object_type == TOUCH_MULTITOUCHSCREEN_T9) {
- id = msg[0] - data->finger_type;
- /* If not a touch event, then keep going */
- if (id < 0 || id >= data->num_fingers)
- continue;
- if (data->finger_mask & (1U << id))
- report_input_data(data);
- if (msg[1] & RELEASE_MSG_MASK) {
- data->fingers[id].z = 0;
- data->fingers[id].w = msg[5];
- data->finger_mask |= 1U << id;
- data->fingers[id].state = MXT_STATE_RELEASE;
- } else if ((msg[1] & DETECT_MSG_MASK) && (msg[1] &
- (PRESS_MSG_MASK | MOVE_MSG_MASK))) {
- #if TOUCH_BOOSTER
- if (!touch_cpu_lock_status)
- mxt_set_dvfs_on(data);
- #endif
- touch_message_flag = 1;
- data->fingers[id].z = msg[6];
- data->fingers[id].w = msg[5];
- data->fingers[id].x =
- (((msg[2] << 4) | (msg[4] >> 4))
- >> data->x_dropbits);
- data->fingers[id].y =
- (((msg[3] << 4) | (msg[4] & 0xF))
- >> data->y_dropbits);
- data->finger_mask |= 1U << id;
- if (msg[1] & PRESS_MSG_MASK) {
- data->fingers[id].state =
- MXT_STATE_PRESS;
- data->fingers[id].mcount = 0;
- } else if (msg[1] & MOVE_MSG_MASK)
- data->fingers[id].mcount += 1;
- #ifdef _SUPPORT_SHAPE_TOUCH_
- data->fingers[id].component = msg[7];
- #endif
- } else if ((msg[1] & SUPPRESS_MSG_MASK)
- && (data->fingers[id].state != MXT_STATE_INACTIVE)) {
- data->fingers[id].z = 0;
- data->fingers[id].w = msg[5];
- data->fingers[id].state = MXT_STATE_RELEASE;
- data->finger_mask |= 1U << id;
- } else {
- /* ignore changed amplitude message */
- if (!((msg[1] & DETECT_MSG_MASK)
- && (msg[1] & AMPLITUDE_MSG_MASK)))
- pr_err("Unknown state %#02x %#02x\n",
- msg[0], msg[1]);
- continue;
- }
- }
- } while (!gpio_get_value(data->gpio_read_done));
- if (data->finger_mask) {
- #if USE_SUMSIZE
- if (sum_size > 0) {
- /* case of normal configuration */
- u8 num_finger = 0;
- u8 i;
- uint16_t t9_sum_size = 0;
- for (i = 0; i < data->num_fingers; i++) {
- if (data->fingers[i].state == MXT_STATE_INACTIVE
- || data->fingers[i].state == MXT_STATE_RELEASE)
- continue;
- t9_sum_size += data->fingers[i].w;
- num_finger++;
- }
- if ((num_finger == 1)
- && ((sum_size-t9_sum_size) >= MAX_SUMSIZE)) {
- pr_info(
- "recalibrate for max sumsize[%d]"
- "t9_sum_size[%d]\n"
- , sum_size, t9_sum_size);
- calibrate_chip_e();
- } else {
- report_input_data(data);
- }
- t9_sum_size = 0;
- sum_size = 0;
- } else {
- /* case of recovery configuration */
- report_input_data(data);
- }
- #else
- report_input_data(data);
- #endif
- }
- return IRQ_HANDLED;
- }
- static int mxt_internal_suspend(struct mxt_data *data)
- {
- int i;
- int count = 0;
- for (i = 0; i < data->num_fingers; i++) {
- if (data->fingers[i].state == MXT_STATE_INACTIVE)
- continue;
- data->fingers[i].z = 0;
- data->fingers[i].state = MXT_STATE_RELEASE;
- count++;
- }
- if (count)
- report_input_data(data);
- #if TOUCH_BOOSTER
- cancel_delayed_work(&data->dvfs_dwork);
- tsp_press_status = 0;
- if (touch_cpu_lock_status) {
- exynos_cpufreq_lock_free(DVFS_LOCK_ID_TSP);
- touch_cpu_lock_status = 0;
- }
- #endif
- data->power_off();
- return 0;
- }
- static int mxt_internal_resume(struct mxt_data *data)
- {
- data->power_on();
- return 0;
- }
- #ifdef CONFIG_HAS_EARLYSUSPEND
- #define mxt_suspend NULL
- #define mxt_resume NULL
- static void mxt_early_suspend(struct early_suspend *h)
- {
- struct mxt_data *data = container_of(h, struct mxt_data,
- early_suspend);
- if (mxt_enabled == 1) {
- pr_info("%s\n", __func__);
- mxt_enabled = 0;
- touch_is_pressed = 0;
- disable_irq(data->client->irq);
- mxt_internal_suspend(data);
- } else
- pr_err("%s. but touch already off\n", __func__);
- }
- static void mxt_late_resume(struct early_suspend *h)
- {
- bool ta_status = 0;
- struct mxt_data *data = container_of(h, struct mxt_data,
- early_suspend);
- if (mxt_enabled == 0) {
- pr_info("%s\n", __func__);
- mxt_internal_resume(data);
- mxt_enabled = 1;
- if (data->read_ta_status) {
- data->read_ta_status(&ta_status);
- pr_info("ta_status is %d\n", ta_status);
- mxt_ta_probe(ta_status);
- }
- treat_median_error_status = 0;
- calibrate_chip_e();
- enable_irq(data->client->irq);
- } else
- pr_err("%s. but touch already on\n", __func__);
- }
- #else
- static int mxt_suspend(struct device *dev)
- {
- struct i2c_client *client = to_i2c_client(dev);
- struct mxt_data *data = i2c_get_clientdata(client);
- mxt_enabled = 0;
- touch_is_pressed = 0;
- #if TOUCH_BOOSTER
- tsp_press_status = 0;
- #endif
- return mxt_internal_suspend(data);
- }
- static int mxt_resume(struct device *dev)
- {
- int ret = 0;
- bool ta_status = 0;
- struct i2c_client *client = to_i2c_client(dev);
- struct mxt_data *data = i2c_get_clientdata(client);
- ret = mxt_internal_resume(data);
- mxt_enabled = 1;
- if (data->read_ta_status) {
- data->read_ta_status(&ta_status);
- pr_info("ta_status is %d\n", ta_status);
- mxt_ta_probe(ta_status);
- }
- return ret;
- }
- #endif
- void Mxt_force_released(void)
- {
- struct mxt_data *data = copy_data;
- int i;
- if (!mxt_enabled) {
- pr_err("mxt_enabled is 0\n");
- return;
- }
- for (i = 0; i < data->num_fingers; i++) {
- if (data->fingers[i].state == MXT_STATE_INACTIVE)
- continue;
- data->fingers[i].z = 0;
- data->fingers[i].state = MXT_STATE_RELEASE;
- }
- report_input_data(data);
- calibrate_chip_e();
- };
- #if SYSFS
- static ssize_t mxt_debug_setting(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
- g_debug_switch = !g_debug_switch;
- return 0;
- }
- static ssize_t mxt_object_setting(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
- struct mxt_data *data = dev_get_drvdata(dev);
- unsigned int object_type;
- unsigned int object_register;
- unsigned int register_value;
- u8 value;
- u8 val;
- int ret;
- u16 address;
- u16 size;
- sscanf(buf, "%u%u%u", &object_type, &object_register, ®ister_value);
- pr_info("object type T%d", object_type);
- pr_info("object register ->Byte%d\n", object_register);
- pr_info("register value %d\n", register_value);
- ret = get_object_info(data, (u8)object_type, &size, &address);
- if (ret) {
- pr_err("fail to get object_info\n");
- return count;
- }
- size = 1;
- value = (u8)register_value;
- write_mem(data, address+(u16)object_register, size, &value);
- read_mem(data, address+(u16)object_register, (u8)size, &val);
- pr_info("T%d Byte%d is %d\n",
- object_type, object_register, val);
- return count;
- }
- static ssize_t mxt_object_show(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
- struct mxt_data *data = dev_get_drvdata(dev);
- unsigned int object_type;
- u8 val;
- int ret;
- u16 address;
- u16 size;
- u16 i;
- sscanf(buf, "%u", &object_type);
- pr_info("object type T%d\n", object_type);
- ret = get_object_info(data, (u8)object_type, &size, &address);
- if (ret) {
- pr_err("fail to get object_info\n");
- return count;
- }
- for (i = 0; i < size; i++) {
- read_mem(data, address+i, 1, &val);
- pr_info("Byte %u --> %u\n", i, val);
- }
- return count;
- }
- struct device *sec_touchscreen;
- struct device *mxt_noise_test;
- /*
- top_left, top_right, center, bottom_left, bottom_right
- */
- unsigned int test_node[5] = {642, 98, 367, 668, 124};
- uint16_t qt_refrence_node[768] = { 0 };
- uint16_t qt_delta_node[768] = { 0 };
- void diagnostic_chip(u8 mode)
- {
- int error;
- u16 t6_address = 0;
- u16 size_one;
- int ret;
- u8 value;
- u16 t37_address = 0;
- ret = get_object_info(copy_data,
- GEN_COMMANDPROCESSOR_T6, &size_one, &t6_address);
- size_one = 1;
- error = write_mem(copy_data, t6_address+5, (u8)size_one, &mode);
- /* QT602240_COMMAND_DIAGNOSTIC, mode); */
- if (error < 0) {
- pr_err("error %s: write_object\n", __func__);
- } else {
- get_object_info(copy_data,
- DEBUG_DIAGNOSTIC_T37, &size_one, &t37_address);
- size_one = 1;
- /* pr_info("diagnostic_chip setting success\n"); */
- read_mem(copy_data, t37_address, (u8)size_one, &value);
- /* pr_info("dianostic_chip mode is %d\n",value); */
- }
- }
- uint8_t read_uint16_t(struct mxt_data *data, uint16_t address, uint16_t *buf)
- {
- uint8_t status;
- uint8_t temp[2];
- status = read_mem(data, address, 2, temp);
- *buf = ((uint16_t)temp[1]<<8) + (uint16_t)temp[0];
- return status;
- }
- void read_dbg_data(uint8_t dbg_mode , uint16_t node, uint16_t *dbg_data)
- {
- u8 read_page, read_point;
- uint8_t mode, page;
- u16 size;
- u16 diagnostic_addr = 0;
- if (!mxt_enabled) {
- pr_err("read_dbg_data. mxt_enabled is 0\n");
- return;
- }
- get_object_info(copy_data,
- DEBUG_DIAGNOSTIC_T37, &size, &diagnostic_addr);
- read_page = node / 64;
- node %= 64;
- read_point = (node * 2) + 2;
- /* Page Num Clear */
- diagnostic_chip(MXT_CTE_MODE);
- msleep(20);
- do {
- if (read_mem(copy_data, diagnostic_addr, 1, &mode)) {
- pr_info("READ_MEM_FAILED\n");
- return;
- }
- } while (mode != MXT_CTE_MODE);
- diagnostic_chip(dbg_mode);
- msleep(20);
- do {
- if (read_mem(copy_data, diagnostic_addr, 1, &mode)) {
- pr_info("READ_MEM_FAILED\n");
- return;
- }
- } while (mode != dbg_mode);
- for (page = 1; page <= read_page; page++) {
- diagnostic_chip(MXT_PAGE_UP);
- msleep(20);
- do {
- if (read_mem(copy_data,
- diagnostic_addr + 1, 1, &mode)) {
- pr_info("READ_MEM_FAILED\n");
- return;
- }
- } while (mode != page);
- }
- if (read_uint16_t(copy_data, diagnostic_addr + read_point, dbg_data)) {
- pr_info("READ_MEM_FAILED\n");
- return;
- }
- }
- #define MIN_VALUE 19744
- #define MAX_VALUE 28884
- #define MIN_VALUE_TA_ERROR_MODE 19125
- #define T48_CALCFG_CHRGON 0x20
- /* caution : should check the sensor level
- this value is depend on tsp tunning state */
- #define SENSOR_GAIN_TAERROR 5
- int read_all_data(uint16_t dbg_mode)
- {
- u8 read_page, read_point;
- u16 max_value = MIN_VALUE, min_value = MAX_VALUE;
- u16 ref_max_value = MAX_VALUE;
- u16 ref_min_value = MIN_VALUE;
- u16 object_address = 0;
- u8 data_buffer[2] = { 0 };
- u8 node = 0;
- int state = 0;
- int num = 0;
- int ret;
- u16 size;
- u8 val = 0;
- u8 sensor_gain = 0;
- bool ta_status = 0;
- if (!mxt_enabled) {
- pr_err("%s : mxt_enabled is 0\n", __func__);
- return 1;
- }
- if (copy_data->read_ta_status) {
- copy_data->read_ta_status(&ta_status);
- pr_info("ta_status is %d\n", ta_status);
- }
- /* check the CHRG_ON bit is set or not */
- /* when CHRG_ON is setted dual x is on so skip read last line*/
- get_object_info(copy_data,
- PROCG_NOISESUPPRESSION_T48, &size, &object_address);
- ret = read_mem(copy_data, object_address+2 , 1, &val);
- if (ret < 0)
- pr_err("TSP read fail : %s", __func__);
- pr_info("%s CALCFG[%#02x]\n", __func__, val);
- val = val & T48_CALCFG_CHRGON;
- /* read sensor gain to check reference value */
- if (val == T48_CALCFG_CHRGON) {
- ret = read_mem(copy_data, object_address+34 , 1, &sensor_gain);
- if (ret < 0)
- pr_err("TSP read fail : %s", __func__);
- sensor_gain = (sensor_gain&0xF0)>>4;
- pr_info("%s BLEN[%d]\n", __func__, sensor_gain);
- if (sensor_gain == SENSOR_GAIN_TAERROR)
- ref_min_value = MIN_VALUE_TA_ERROR_MODE;
- }
- /* Page Num Clear */
- diagnostic_chip(MXT_CTE_MODE);
- msleep(30);/* msleep(20); */
- diagnostic_chip(dbg_mode);
- msleep(30);/* msleep(20); */
- ret = get_object_info(copy_data,
- DEBUG_DIAGNOSTIC_T37, &size, &object_address);
- msleep(50); /* msleep(20); */
- /* 768/64 */
- for (read_page = 0 ; read_page < 12; read_page++) {
- for (node = 0; node < 64; node++) {
- read_point = (node * 2) + 2;
- read_mem(copy_data,
- object_address+(u16)read_point, 2, data_buffer);
- qt_refrence_node[num] = ((uint16_t)data_buffer[1]<<8)
- + (uint16_t)data_buffer[0];
- /* last X line has 1/2 reference during
- TA mode So do not check min/max value */
- if ((val != T48_CALCFG_CHRGON)
- || (val == T48_CALCFG_CHRGON && (num < 736))) {
- if ((qt_refrence_node[num] < ref_min_value)
- || (qt_refrence_node[num] > ref_max_value)) {
- if (sensor_gain == SENSOR_GAIN_TAERROR)
- state = 2;
- else
- state = 1;
- pr_err(
- "qt_refrence_node[%3d] = %5d\n"
- , num, qt_refrence_node[num]);
- }
- if (data_buffer[0] != 0) {
- if (qt_refrence_node[num] > max_value)
- max_value =
- qt_refrence_node[num];
- if (qt_refrence_node[num] < min_value)
- min_value =
- qt_refrence_node[num];
- }
- }
- num++;
- /* all node => 24 * 32 = 768 => (12page * 64) */
- /* if ((read_page == 11) && (node == 64))
- break; */
- if (qt_refrence_node[num-1] == 0)
- pr_err("qt_refrence_node"
- "[%d] = 0\n", num);
- if (num == 768)
- break;
- }
- diagnostic_chip(MXT_PAGE_UP);
- msleep(35);
- if (num == 768)
- break;
- }
- if ((max_value - min_value) > 4500) {
- pr_err("diff = %d, max_value = %d, min_value = %d\n",
- (max_value - min_value), max_value, min_value);
- state = 1;
- }
- return state;
- }
- int read_all_delta_data(uint16_t dbg_mode)
- {
- u8 read_page, read_point;
- u16 object_address = 0;
- u8 data_buffer[2] = { 0 };
- u8 node = 0;
- int state = 0;
- int num = 0;
- int ret;
- u16 size;
- if (!mxt_enabled) {
- pr_err("%s : mxt_enabled is 0\n", __func__);
- return 1;
- }
- /* Page Num Clear */
- diagnostic_chip(MXT_CTE_MODE);
- msleep(30);/* msleep(20); */
- diagnostic_chip(dbg_mode);
- msleep(30);/* msleep(20); */
- ret = get_object_info(copy_data,
- DEBUG_DIAGNOSTIC_T37, &size, &object_address);
- /*jerry no need to leave it */
- #if 0
- for (i = 0; i < 5; i++) {
- if (data_buffer[0] == dbg_mode)
- break;
- msleep(20);
- }
- #else
- msleep(50); /* msleep(20); */
- #endif
- /* 768/64 */
- for (read_page = 0 ; read_page < 12; read_page++) {
- for (node = 0; node < 64; node++) {
- read_point = (node * 2) + 2;
- read_mem(copy_data,
- object_address+(u16)read_point, 2, data_buffer);
- qt_delta_node[num] =
- ((uint16_t)data_buffer[1]<<8)
- + (uint16_t)data_buffer[0];
- num++;
- /* all node => 24 * 32 = 768 => (12page * 64) */
- /*if ((read_page == 11) && (node == 64))
- break;*/
- }
- diagnostic_chip(MXT_PAGE_UP);
- msleep(35);
- }
- return state;
- }
- int find_channel(uint16_t dbg_mode)
- {
- u8 read_page, read_point;
- u16 object_address = 0;
- u8 data_buffer[2] = { 0 };
- u8 node = 0;
- int state = 0;
- int num = 0;
- int ret;
- u16 size;
- u16 delta_val = 0;
- u16 max_val = 0;
- if (!mxt_enabled) {
- pr_err("%s : mxt_enabled is 0\n", __func__);
- return 1;
- }
- /* Page Num Clear */
- diagnostic_chip(MXT_CTE_MODE);
- msleep(30);/* msleep(20); */
- diagnostic_chip(dbg_mode);
- msleep(30);/* msleep(20); */
- ret = get_object_info(copy_data,
- DEBUG_DIAGNOSTIC_T37, &size, &object_address);
- /*jerry no need to leave it */
- #if 0
- for (i = 0; i < 5; i++) {
- if (data_buffer[0] == dbg_mode)
- break;
- msleep(20);
- }
- #else
- msleep(50); /* msleep(20); */
- #endif
- /* 768/64 */
- for (read_page = 0 ; read_page < 12; read_page++) {
- for (node = 0; node < 64; node++) {
- read_point = (node * 2) + 2;
- read_mem(copy_data,
- object_address+(u16)read_point, 2, data_buffer);
- delta_val = ((uint16_t)data_buffer[1]<<8)
- + (uint16_t)data_buffer[0];
- if (delta_val > 32767)
- delta_val = 65535 - delta_val;
- if (delta_val > max_val) {
- max_val = delta_val;
- state = (read_point - 2)/2 +
- (read_page * 64);
- }
- num++;
- /* all node => 24 * 32 = 768 => (12page * 64) */
- /*if ((read_page == 11) && (node == 64))
- break;*/
- }
- diagnostic_chip(MXT_PAGE_UP);
- msleep(35);
- }
- return state;
- }
- static ssize_t find_channel_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
- {
- int status = 0;
- status = find_channel(MXT_DELTA_MODE);
- return sprintf(buf, "%u\n", status);
- }
- #endif
- static int mxt_check_bootloader(struct i2c_client *client,
- unsigned int state)
- {
- u8 val;
- u8 temp;
- recheck:
- if (i2c_master_recv(client, &val, 1) != 1)
- return -EIO;
- if (val & 0x20) {
- if (i2c_master_recv(client, &temp, 1) != 1)
- return -EIO;
- if (i2c_master_recv(client, &temp, 1) != 1)
- return -EIO;
- val &= ~0x20;
- }
- if ((val & 0xF0) == MXT_APP_CRC_FAIL) {
- pr_info("MXT_APP_CRC_FAIL\n");
- if (i2c_master_recv(client, &val, 1) != 1)
- return -EIO;
- if (val & 0x20) {
- if (i2c_master_recv(client, &temp, 1) != 1)
- return -EIO;
- if (i2c_master_recv(client, &temp, 1) != 1)
- return -EIO;
- val &= ~0x20;
- }
- }
- 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;
- }
- if (val != state) {
- pr_err("Unvalid bootloader mode state\n");
- return -EINVAL;
- }
- return 0;
- }
- static int mxt_unlock_bootloader(struct i2c_client *client)
- {
- u8 buf[2];
- buf[0] = MXT_UNLOCK_CMD_LSB;
- buf[1] = MXT_UNLOCK_CMD_MSB;
- if (i2c_master_send(client, buf, 2) != 2) {
- pr_err("%s: i2c send failed\n",
- __func__);
- return -EIO;
- }
- return 0;
- }
- static int mxt_fw_write(struct i2c_client *client,
- const u8 *data, unsigned int frame_size)
- {
- if (i2c_master_send(client, data, frame_size) != frame_size) {
- pr_err("%s: i2c send failed\n", __func__);
- return -EIO;
- }
- return 0;
- }
- static int mxt_load_fw(struct device *dev, const char *fn)
- {
- struct mxt_data *data = copy_data;
- struct i2c_client *client = copy_data->client;
- unsigned int frame_size;
- unsigned int pos = 0;
- int ret;
- u16 obj_address = 0;
- u16 size_one;
- u8 value;
- unsigned int object_register;
- int check_frame_crc_error = 0;
- int check_wating_frame_data_error = 0;
- #if READ_FW_FROM_HEADER
- struct firmware *fw = NULL;
- pr_info("mxt_load_fw start from header!!!\n");
- fw = kzalloc(sizeof(struct firmware), GFP_KERNEL);
- fw->data = firmware_mXT;
- fw->size = sizeof(firmware_mXT);
- #else
- const struct firmware *fw = NULL;
- pr_info("mxt_load_fw startl!!!\n");
- ret = request_firmware(&fw, fn, &client->dev);
- if (ret) {
- pr_err("Unable to open firmware %s\n", fn);
- return ret;
- }
- #endif
- /* Change to the bootloader mode */
- object_register = 0;
- value = (u8)MXT_BOOT_VALUE;
- ret = get_object_info(data,
- GEN_COMMANDPROCESSOR_T6, &size_one, &obj_address);
- if (ret) {
- pr_err("fail to get object_info\n");
- release_firmware(fw);
- return ret;
- }
- size_one = 1;
- write_mem(data, obj_address+(u16)object_register, (u8)size_one, &value);
- msleep(MXT_SW_RESET_TIME);
- /* Change to slave address of bootloader */
- if (client->addr == MXT_APP_LOW)
- client->addr = MXT_BOOT_LOW;
- else
- client->addr = MXT_BOOT_HIGH;
- ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
- if (ret)
- goto out;
- /* Unlock bootloader */
- mxt_unlock_bootloader(client);
- while (pos < fw->size) {
- ret = mxt_check_bootloader(client,
- MXT_WAITING_FRAME_DATA);
- if (ret) {
- check_wating_frame_data_error++;
- if (check_wating_frame_data_error > 10) {
- pr_err("firm update fail. wating_frame_data err\n");
- goto out;
- } else {
- pr_err("check_wating_frame_data_error = %d, retry\n",
- check_wating_frame_data_error);
- continue;
- }
- }
- frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1));
- /* 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) {
- check_frame_crc_error++;
- if (check_frame_crc_error > 10) {
- pr_err("firm update fail. frame_crc err\n");
- goto out;
- } else {
- pr_err("check_frame_crc_error = %d, retry\n",
- check_frame_crc_error);
- continue;
- }
- }
- pos += frame_size;
- pr_info("Updated %d bytes / %zd bytes\n",
- pos, fw->size);
- msleep(20);
- }
- out:
- #if READ_FW_FROM_HEADER
- kfree(fw);
- #else
- release_firmware(fw);
- #endif
- /* Change to slave address of application */
- if (client->addr == MXT_BOOT_LOW)
- client->addr = MXT_APP_LOW;
- else
- client->addr = MXT_APP_HIGH;
- return ret;
- }
- static int mxt_load_fw_bootmode(struct device *dev, const char *fn)
- {
- struct i2c_client *client = copy_data->client;
- unsigned int frame_size;
- unsigned int pos = 0;
- int ret;
- int check_frame_crc_error = 0;
- int check_wating_frame_data_error = 0;
- #if READ_FW_FROM_HEADER
- struct firmware *fw = NULL;
- pr_info("mxt_load_fw start from header!!!\n");
- fw = kzalloc(sizeof(struct firmware), GFP_KERNEL);
- fw->data = firmware_mXT;
- fw->size = sizeof(firmware_mXT);
- #else
- const struct firmware *fw = NULL;
- pr_info("mxt_load_fw start!!!\n");
- ret = request_firmware(&fw, fn, &client->dev);
- if (ret) {
- pr_err("Unable to open firmware %s\n", fn);
- return ret;
- }
- #endif
- /* Unlock bootloader */
- mxt_unlock_bootloader(client);
- while (pos < fw->size) {
- ret = mxt_check_bootloader(client,
- MXT_WAITING_FRAME_DATA);
- if (ret) {
- check_wating_frame_data_error++;
- if (check_wating_frame_data_error > 10) {
- pr_err("firm update fail. wating_frame_data err\n");
- goto out;
- } else {
- pr_err("check_wating_frame_data_error = %d, retry\n",
- check_wating_frame_data_error);
- continue;
- }
- }
- frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1));
- /* 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) {
- check_frame_crc_error++;
- if (check_frame_crc_error > 10) {
- pr_err("firm update fail. frame_crc err\n");
- goto out;
- } else {
- pr_err("check_frame_crc_error = %d, retry\n",
- check_frame_crc_error);
- continue;
- }
- }
- pos += frame_size;
- pr_info("Updated %d bytes / %zd bytes\n",
- pos, fw->size);
- msleep(20);
- }
- out:
- #if READ_FW_FROM_HEADER
- kfree(fw);
- #else
- release_firmware(fw);
- #endif
- /* Change to slave address of application */
- if (client->addr == MXT_BOOT_LOW)
- client->addr = MXT_APP_LOW;
- else
- client->addr = MXT_APP_HIGH;
- return ret;
- }
- #if SYSFS
- static ssize_t set_refer0_mode_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- uint16_t mxt_reference = 0;
- read_dbg_data(MXT_REFERENCE_MODE, test_node[0], &mxt_reference);
- return sprintf(buf, "%u\n", mxt_reference);
- }
- static ssize_t set_refer1_mode_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- uint16_t mxt_reference = 0;
- read_dbg_data(MXT_REFERENCE_MODE, test_node[1], &mxt_reference);
- return sprintf(buf, "%u\n", mxt_reference);
- }
- static ssize_t set_refer2_mode_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- uint16_t mxt_reference = 0;
- read_dbg_data(MXT_REFERENCE_MODE, test_node[2], &mxt_reference);
- return sprintf(buf, "%u\n", mxt_reference);
- }
- static ssize_t set_refer3_mode_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- uint16_t mxt_reference = 0;
- read_dbg_data(MXT_REFERENCE_MODE, test_node[3], &mxt_reference);
- return sprintf(buf, "%u\n", mxt_reference);
- }
- static ssize_t set_refer4_mode_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- uint16_t mxt_reference = 0;
- read_dbg_data(MXT_REFERENCE_MODE, test_node[4], &mxt_reference);
- return sprintf(buf, "%u\n", mxt_reference);
- }
- static ssize_t set_delta0_mode_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- uint16_t mxt_delta = 0;
- read_dbg_data(MXT_DELTA_MODE, test_node[0], &mxt_delta);
- if (mxt_delta < 32767)
- return sprintf(buf, "%u\n", mxt_delta);
- else
- mxt_delta = 65535 - mxt_delta;
- if (mxt_delta)
- return sprintf(buf, "-%u\n", mxt_delta);
- else
- return sprintf(buf, "%u\n", mxt_delta);
- }
- static ssize_t set_delta1_mode_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- uint16_t mxt_delta = 0;
- read_dbg_data(MXT_DELTA_MODE, test_node[1], &mxt_delta);
- if (mxt_delta < 32767)
- return sprintf(buf, "%u\n", mxt_delta);
- else
- mxt_delta = 65535 - mxt_delta;
- if (mxt_delta)
- return sprintf(buf, "-%u\n", mxt_delta);
- else
- return sprintf(buf, "%u\n", mxt_delta);
- }
- static ssize_t set_delta2_mode_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- uint16_t mxt_delta = 0;
- read_dbg_data(MXT_DELTA_MODE, test_node[2], &mxt_delta);
- if (mxt_delta < 32767)
- return sprintf(buf, "%u\n", mxt_delta);
- else
- mxt_delta = 65535 - mxt_delta;
- if (mxt_delta)
- return sprintf(buf, "-%u\n", mxt_delta);
- else
- return sprintf(buf, "%u\n", mxt_delta);
- }
- static ssize_t set_delta3_mode_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- uint16_t mxt_delta = 0;
- read_dbg_data(MXT_DELTA_MODE, test_node[3], &mxt_delta);
- if (mxt_delta < 32767)
- return sprintf(buf, "%u\n", mxt_delta);
- else
- mxt_delta = 65535 - mxt_delta;
- if (mxt_delta)
- return sprintf(buf, "-%u\n", mxt_delta);
- else
- return sprintf(buf, "%u\n", mxt_delta);
- }
- static ssize_t set_delta4_mode_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- uint16_t mxt_delta = 0;
- read_dbg_data(MXT_DELTA_MODE, test_node[4], &mxt_delta);
- if (mxt_delta < 32767)
- return sprintf(buf, "%u\n", mxt_delta);
- else
- mxt_delta = 65…
Large files files are truncated, but you can click here to view the full file