aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen/mxt540s.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/touchscreen/mxt540s.c')
-rw-r--r--drivers/input/touchscreen/mxt540s.c2131
1 files changed, 0 insertions, 2131 deletions
diff --git a/drivers/input/touchscreen/mxt540s.c b/drivers/input/touchscreen/mxt540s.c
deleted file mode 100644
index 6c66adb..0000000
--- a/drivers/input/touchscreen/mxt540s.c
+++ /dev/null
@@ -1,2131 +0,0 @@
-/*
- * Copyright (C) 2012, 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.
- *
- */
-
-#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/slab.h>
-#include <linux/gpio.h>
-#include <linux/i2c/mxt540s.h>
-#include <asm/unaligned.h>
-#include <linux/firmware.h>
-#include <linux/string.h>
-#ifdef CONFIG_HAS_EARLYSUSPEND
-#include <linux/earlysuspend.h>
-#endif
-
-#include "mxt540s_dev.h"
-
-int mxt_read_mem(struct mxt_data *data, u16 reg, u8 len, u8 *buf)
-{
- int ret = 0, i = 0;
- 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,
- },
- };
-
- for (i = 0; i < 3 ; i++) {
- ret = i2c_transfer(data->client->adapter, msg, 2);
- if (ret < 0)
- dev_err(&data->client->dev, "%s fail[%d] address[0x%x]\n",
- __func__, ret, le_reg);
- else
- break;
- }
- return ret == 2 ? 0 : -EIO;
-}
-
-int mxt_write_mem(struct mxt_data *data,
- u16 reg, u8 len, const u8 *buf)
-{
- int ret = 0, i = 0;
- u8 tmp[len + 2];
-
- put_unaligned_le16(cpu_to_le16(reg), tmp);
- memcpy(tmp + 2, buf, len);
-
- for (i = 0; i < 3 ; i++) {
- ret = i2c_master_send(data->client, tmp, sizeof(tmp));
- if (ret < 0)
- dev_err(&data->client->dev,
- "%s %d times write error on address[0x%x,0x%x]\n",
- __func__, i, tmp[1], tmp[0]);
- else
- break;
- }
-
- return ret == sizeof(tmp) ? 0 : -EIO;
-}
-
-struct mxt_object *
- mxt_get_object(struct mxt_data *data, u8 object_type)
-{
- struct mxt_object *object;
- int i;
-
- if (!data->objects)
- return NULL;
-
- for (i = 0; i < data->info.object_num; i++) {
- object = data->objects + i;
- if (object->object_type == object_type)
- return object;
- }
-
- dev_err(&data->client->dev, "Invalid object type T%d\n",
- object_type);
-
- return NULL;
-}
-
-int mxt_read_object(struct mxt_data *data,
- u8 type, u8 offset, u8 *val)
-{
- struct mxt_object *object;
- u16 reg;
-
- object = mxt_get_object(data, type);
- if (!object)
- return -EINVAL;
-
- reg = object->start_address;
-
- return mxt_read_mem(data, reg + offset, 1, val);
-}
-
-int mxt_write_object(struct mxt_data *data,
- u8 type, u8 offset, u8 val)
-{
- struct mxt_object *object;
- u16 reg;
-
- object = mxt_get_object(data, type);
- if (!object)
- return -EINVAL;
-
- if (offset >= object->size * object->instances) {
- dev_err(&data->client->dev,
- "Tried to write outside object T%d offset:%d, size:%d\n",
- type, offset, object->size);
- return -EINVAL;
- }
- reg = object->start_address;
- return mxt_write_mem(data, reg + offset, 1, &val);
-}
-
-static int mxt_reset(struct mxt_data *data)
-{
- u8 buf = 1u;
- return mxt_write_mem(data, data->cmd_proc + CMD_RESET_OFFSET, 1, &buf);
-}
-
-static int mxt_backup(struct mxt_data *data)
-{
- u8 buf = 0x55u;
- return mxt_write_mem(data, data->cmd_proc + CMD_BACKUP_OFFSET, 1, &buf);
-}
-
-static int mxt_start(struct mxt_data *data)
-{
- int error;
-
- /* Touch report enable */
- error = mxt_write_object(data, TOUCH_MULTITOUCHSCREEN_T9,
- MXT_T9_CTRL, data->tsp_ctrl);
-
- if (error)
- dev_err(&data->client->dev, "Fail to start touch\n");
-
- return error;
-}
-
-static void mxt_stop(struct mxt_data *data)
-{
- /* Touch report disable */
- mxt_write_object(data, TOUCH_MULTITOUCHSCREEN_T9, MXT_T9_CTRL, 0);
-}
-
-static int mxt_check_instance(struct mxt_data *data, u8 object_type)
-{
- int i;
-
- for (i = 0; i < data->info.object_num; i++) {
- if (data->objects[i].object_type == object_type)
- return data->objects[i].instances;
- }
- return 0;
-}
-
-static u32 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 mxt_calculate_infoblock_crc(struct mxt_data *data,
- u32 *crc_pointer)
-{
- u32 crc = 0;
- u8 mem[7 + data->info.object_num * 6];
- int ret;
- int i;
-
- ret = mxt_read_mem(data, 0, sizeof(mem), mem);
-
- if (ret)
- return ret;
-
- 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;
-}
-
-static int mxt_read_info_crc(struct mxt_data *data, u32 *crc_pointer)
-{
- u16 crc_address;
- u8 msg[3];
- int ret;
-
- /* Read Info block CRC address */
- crc_address = OBJECT_TABLE_START_ADDRESS +
- data->info.object_num * OBJECT_TABLE_ELEMENT_SIZE;
-
- ret = mxt_read_mem(data, crc_address, 3, msg);
- if (ret)
- return ret;
-
- *crc_pointer = msg[0] | (msg[1] << 8) | (msg[2] << 16);
-
- return 0;
-}
-
-static int mxt_reportid_to_type(struct mxt_data *data,
- u8 report_id, u8 *instance)
-{
- if (report_id <= data->max_report_id) {
- *instance = data->rid_map[report_id].instance;
- return data->rid_map[report_id].object_type;
- } else
- return 0;
-}
-
-static int mxt_read_config_crc(struct mxt_data *data, u32 *crc_pointer)
-{
- struct device *dev = &data->client->dev;
- struct mxt_object *object;
- u8 msg[data->msg_object_size];
- int error, try = 0;
- int fail_count = data->max_report_id * 2;
- u8 object_type, instance;
-
- object = mxt_get_object(data, GEN_COMMANDPROCESSOR_T6);
- if (!object)
- return -EIO;
-
- /* Try to read the config checksum of the existing cfg */
- mxt_write_object(data, GEN_COMMANDPROCESSOR_T6,
- CMD_REPORTATLL_OFFSET, 1);
-
- /* Read message from command processor, which only has one report ID */
- while (++try < fail_count) {
- error = mxt_read_mem(data, data->msg_proc, sizeof(msg), msg);
- if (error)
- return error;
-
- object_type = mxt_reportid_to_type(data, msg[0] , &instance);
- if (object_type == RESERVED_T0)
- return -EINVAL;
-
- if (object_type == GEN_COMMANDPROCESSOR_T6)
- break;
- }
-
- if (error) {
- dev_err(dev, "Failed to retrieve CRC\n");
- return error;
- }
-
- /* Bytes 1-3 are the checksum. */
- *crc_pointer = msg[2] | (msg[3] << 8) | (msg[4] << 16);
-
- return 0;
-}
-
-static int mxt_get_id_info(struct mxt_data *data)
-{
- int ret = 0;
- u8 id[ID_BLOCK_SIZE];
-
- /* Read IC information */
- ret = mxt_read_mem(data, 0, sizeof(id), id);
- if (ret) {
- dev_err(&data->client->dev, "Read fail. IC information\n");
- goto out;
- } else {
- dev_info(&data->client->dev,
- "family: 0x%x variant: 0x%x version: 0x%x"
- " build: 0x%x matrix X,Y size: %d,%d"
- " number of obect: %d\n"
- , id[0], id[1], id[2], id[3], id[4], id[5], id[6]);
- data->info.family_id = id[0];
- data->info.variant_id = id[1];
- data->info.version = id[2];
- data->info.build = id[3];
- data->info.matrix_xsize = id[4];
- data->info.matrix_ysize = id[5];
- data->info.object_num = id[6];
- }
-
-out:
- return ret;
-}
-
-static int mxt_get_object_table(struct mxt_data *data)
-{
- int ret = 0;
- int i;
- u8 type_count = 0;
-
- ret = mxt_read_mem(data, OBJECT_TABLE_START_ADDRESS,
- data->info.object_num * sizeof(*data->objects),
- (u8 *)data->objects);
-
- if (ret)
- goto out;
-
- data->max_report_id = 0;
-
- for (i = 0; i < data->info.object_num; i++) {
- data->objects[i].start_address =
- le16_to_cpu(data->objects[i].start_address);
- /* size and instance values are smaller than atual value */
- data->objects[i].size += 1;
- data->objects[i].instances += 1;
- data->max_report_id += data->objects[i].num_report_ids *
- (data->objects[i].instances);
-
- switch (data->objects[i].object_type) {
- case GEN_MESSAGEPROCESSOR_T5:
- data->msg_object_size = data->objects[i].size;
- data->msg_proc = data->objects[i].start_address;
- dev_dbg(&data->client->dev,
- "mesage object size: %d message address: 0x%x\n",
- data->msg_object_size, data->msg_proc);
- break;
- case GEN_COMMANDPROCESSOR_T6:
- data->cmd_proc = data->objects[i].start_address;
- break;
- case TOUCH_MULTITOUCHSCREEN_T9:
- data->finger_report_id = type_count + 1;
- dev_dbg(&data->client->dev, "Finger report id: %d\n",
- data->finger_report_id);
- break;
- }
-
- if (data->objects[i].num_report_ids) {
- type_count += data->objects[i].num_report_ids *
- (data->objects[i].instances);
- }
- }
-
- dev_info(&data->client->dev, "maXTouch: %d Objects\n",
- data->info.object_num);
-#ifdef DEBUG
- for (i = 0; i < data->info.object_num; i++) {
- dev_dbg(&data->client->dev,
- "Object:T%d\t\t\t Address:0x%x\tSize:%d\tInstance:%d\tReport Id's:%d\n",
- data->objects[i].object_type,
- data->objects[i].start_address,
- data->objects[i].size,
- data->objects[i].instances,
- data->objects[i].num_report_ids);
- }
-#endif
-
-out:
- return ret;
-}
-
-static void __devinit mxt_make_reportid_table(struct mxt_data *data)
-{
- struct mxt_object *objects = data->objects;
- int i, j;
- int cur_id, sta_id;
-
- data->rid_map[0].instance = 0;
- data->rid_map[0].object_type = 0;
- cur_id = 1;
-
- for (i = 0; i < data->info.object_num; i++) {
- if (objects[i].num_report_ids == 0)
- continue;
- for (j = 1; j <= objects[i].instances; j++) {
- for (sta_id = cur_id;
- cur_id < (sta_id + objects[i].num_report_ids);
- cur_id++) {
-
- data->rid_map[cur_id].instance = j;
- data->rid_map[cur_id].object_type =
- objects[i].object_type;
- }
- }
- }
-
- dev_info(&data->client->dev, "maXTouch: %d report ID\n",
- data->max_report_id);
-
-#ifdef DEBUG
- for (i = 0; i < data->max_report_id; i++) {
- dev_dbg(&data->client->dev, "Report_id[%d]:\tT%d\n",
- i, data->rid_map[i].object_type);
- }
-#endif
-}
-
-static int mxt_init_write_config(struct mxt_data *data,
- u8 type, const u8 *cfg)
-{
- struct mxt_object *object;
- u8 *temp;
- int ret;
-
- object = mxt_get_object(data, type);
- if (!object)
- return -EINVAL;
-
- if ((object->size == 0) || (object->start_address == 0)) {
- dev_err(&data->client->dev,
- "%s error object_type T%d\n", __func__, type);
- return -ENODEV;
- }
-
- ret = mxt_write_mem(data, object->start_address,
- object->size, cfg);
- if (ret) {
- dev_err(&data->client->dev,
- "%s write error T%d address[0x%x]\n",
- __func__, type, object->start_address);
- return ret;
- }
-
- if (mxt_check_instance(data, type)) {
- temp = kzalloc(object->size, GFP_KERNEL);
-
- if (temp == NULL)
- return -ENOMEM;
-
- ret |= mxt_write_mem(data, object->start_address + object->size,
- object->size, temp);
- kfree(temp);
- }
-
- return ret;
-}
-
-static int mxt_write_config_from_pdata(struct mxt_data *data)
-{
- struct device *dev = &data->client->dev;
- u8 **tsp_config = (u8 **)data->pdata->config;
- u8 i;
- int ret;
-
- if (!tsp_config) {
- dev_info(dev, "No cfg data in pdata\n");
- return 0;
- }
-
- for (i = 0; tsp_config[i][0] != RESERVED_T255; i++) {
- ret = mxt_init_write_config(data, tsp_config[i][0],
- tsp_config[i] + 1);
- if (ret)
- return ret;
-
- if (tsp_config[i][0] == TOUCH_MULTITOUCHSCREEN_T9) {
- /* Are x and y inverted? */
- if (tsp_config[i][10] & 0x1) {
- data->x_dropbits =
- (!(tsp_config[i][22] & 0xC)) << 1;
- data->y_dropbits =
- (!(tsp_config[i][20] & 0xC)) << 1;
- } else {
- data->x_dropbits =
- (!(tsp_config[i][20] & 0xC)) << 1;
- data->y_dropbits =
- (!(tsp_config[i][22] & 0xC)) << 1;
- }
- }
- }
- return ret;
-}
-
-#if DUAL_CFG
-static int mxt_write_config(struct mxt_fw_info *fw_info)
-{
- struct mxt_data *data = fw_info->data;
- struct device *dev = &data->client->dev;
- struct mxt_object *object;
- struct mxt_cfg_data *cfg_data;
- u32 current_crc;
- u8 i, val = 0;
- u16 reg, index;
- int ret;
- u32 cfg_length = data->cfg_len = fw_info->cfg_len / 2 ;
-
- if (!fw_info->ta_cfg_raw_data && !fw_info->batt_cfg_raw_data) {
- dev_info(dev, "No cfg data in file\n");
- ret = mxt_write_config_from_pdata(data);
- return ret;
- }
-
- /* Get config CRC from device */
- ret = mxt_read_config_crc(data, &current_crc);
- if (ret)
- return ret;
-
- /* Check Version information */
- if (fw_info->fw_ver != data->info.version) {
- dev_err(dev, "Warning: version mismatch! %s\n", __func__);
- return 0;
- }
- if (fw_info->build_ver != data->info.build) {
- dev_err(dev, "Warning: build num mismatch! %s\n", __func__);
- return 0;
- }
-
- /* Check config CRC */
- if (current_crc == fw_info->cfg_crc) {
- dev_info(dev, "Skip writing Config:[CRC 0x%06X]\n",
- current_crc);
- return 0;
- }
-
- dev_info(dev, "Writing Config:[CRC 0x%06X!=0x%06X]\n",
- current_crc, fw_info->cfg_crc);
-
- /* Get the address of configuration data */
- data->batt_cfg_raw_data = fw_info->batt_cfg_raw_data;
- data->ta_cfg_raw_data = fw_info->ta_cfg_raw_data =
- fw_info->batt_cfg_raw_data + cfg_length;
-
- /* Write config info */
- for (index = 0; index < cfg_length;) {
- if (index + sizeof(struct mxt_cfg_data) >= cfg_length) {
- dev_err(dev, "index(%d) of cfg_data exceeded total size(%d)!!\n",
- index + sizeof(struct mxt_cfg_data),
- cfg_length);
- return -EINVAL;
- }
-
- /* Get the info about each object */
- if (data->charging_mode)
- cfg_data = (struct mxt_cfg_data *)
- (&fw_info->ta_cfg_raw_data[index]);
- else
- cfg_data = (struct mxt_cfg_data *)
- (&fw_info->batt_cfg_raw_data[index]);
-
- index += sizeof(struct mxt_cfg_data) + cfg_data->size;
- if (index > cfg_length) {
- dev_err(dev, "index(%d) of cfg_data exceeded total size(%d) in T%d object!!\n",
- index, cfg_length, cfg_data->type);
- return -EINVAL;
- }
-
- object = mxt_get_object(data, cfg_data->type);
- if (!object) {
- dev_err(dev, "T%d is Invalid object type\n",
- cfg_data->type);
- return -EINVAL;
- }
-
- /* Check and compare the size, instance of each object */
- if (cfg_data->size > object->size) {
- dev_err(dev, "T%d Object length exceeded!\n",
- cfg_data->type);
- return -EINVAL;
- }
- if (cfg_data->instance >= object->instances) {
- dev_err(dev, "T%d Object instances exceeded!\n",
- cfg_data->type);
- return -EINVAL;
- }
-
- dev_dbg(dev, "Writing config for obj %d len %d instance %d (%d/%d)\n",
- cfg_data->type, object->size,
- cfg_data->instance, index, cfg_length);
-
- reg = object->start_address + object->size * cfg_data->instance;
-
- /* Write register values of each object */
- ret = mxt_write_mem(data, reg, cfg_data->size,
- cfg_data->register_val);
- if (ret) {
- dev_err(dev, "Write T%d Object failed\n",
- object->object_type);
- return ret;
- }
-
- /*
- * If firmware is upgraded, new bytes may be added to end of
- * objects. It is generally forward compatible to zero these
- * bytes - previous behaviour will be retained. However
- * this does invalidate the CRC and will force a config
- * download every time until the configuration is updated.
- */
- if (cfg_data->size < object->size) {
- dev_err(dev, "Warning: zeroing %d byte(s) in T%d\n",
- object->size - cfg_data->size, cfg_data->type);
-
- for (i = cfg_data->size + 1; i < object->size; i++) {
- ret = mxt_write_mem(data, reg + i, 1, &val);
- if (ret)
- return ret;
- }
- }
- }
- dev_info(dev, "Updated configuration\n");
-
- return ret;
-}
-#else
-static int mxt_write_config(struct mxt_fw_info *fw_info)
-{
- struct mxt_data *data = fw_info->data;
- struct device *dev = &data->client->dev;
- struct mxt_object *object;
- struct mxt_cfg_data *cfg_data;
- u32 current_crc;
- u8 i, val = 0;
- u16 reg, index;
- int ret;
-
- if (!fw_info->cfg_raw_data) {
- dev_info(dev, "No cfg data in file\n");
- ret = mxt_write_config_from_pdata(data);
- return ret;
- }
-
- /* Get config CRC from device */
- ret = mxt_read_config_crc(data, &current_crc);
- if (ret)
- return ret;
-
- /* Check Version information */
- if (fw_info->fw_ver != data->info.version) {
- dev_err(dev, "Warning: version mismatch! %s\n", __func__);
- return 0;
- }
- if (fw_info->build_ver != data->info.build) {
- dev_err(dev, "Warning: build num mismatch! %s\n", __func__);
- return 0;
- }
-
- /* Check config CRC */
- if (current_crc == fw_info->cfg_crc) {
- dev_info(dev, "Skip writing Config:[CRC 0x%06X]\n",
- current_crc);
- return 0;
- }
-
- dev_info(dev, "Writing Config:[CRC 0x%06X!=0x%06X]\n",
- current_crc, fw_info->cfg_crc);
-
- /* Write config info */
- for (index = 0; index < fw_info->cfg_len;) {
-
- if (index + sizeof(struct mxt_cfg_data) >= fw_info->cfg_len) {
- dev_err(dev, "index(%d) of cfg_data exceeded total size(%d)!!\n",
- index + sizeof(struct mxt_cfg_data),
- fw_info->cfg_len);
- return -EINVAL;
- }
-
- /* Get the info about each object */
- cfg_data = (struct mxt_cfg_data *)
- (&fw_info->cfg_raw_data[index]);
-
- index += sizeof(struct mxt_cfg_data) + cfg_data->size;
- if (index > fw_info->cfg_len) {
- dev_err(dev, "index(%d) of cfg_data exceeded total size(%d) in T%d object!!\n",
- index, fw_info->cfg_len, cfg_data->type);
- return -EINVAL;
- }
-
- object = mxt_get_object(data, cfg_data->type);
- if (!object) {
- dev_err(dev, "T%d is Invalid object type\n",
- cfg_data->type);
- return -EINVAL;
- }
-
- /* Check and compare the size, instance of each object */
- if (cfg_data->size > object->size) {
- dev_err(dev, "T%d Object length exceeded!\n",
- cfg_data->type);
- return -EINVAL;
- }
- if (cfg_data->instance >= object->instances) {
- dev_err(dev, "T%d Object instances exceeded!\n",
- cfg_data->type);
- return -EINVAL;
- }
-
- dev_dbg(dev, "Writing config for obj %d len %d instance %d (%d/%d)\n",
- cfg_data->type, object->size,
- cfg_data->instance, index, fw_info->cfg_len);
-
- reg = object->start_address + object->size * cfg_data->instance;
-
- /* Write register values of each object */
- ret = mxt_write_mem(data, reg, cfg_data->size,
- cfg_data->register_val);
- if (ret) {
- dev_err(dev, "Write T%d Object failed\n",
- object->object_type);
- return ret;
- }
-
- /*
- * If firmware is upgraded, new bytes may be added to end of
- * objects. It is generally forward compatible to zero these
- * bytes - previous behaviour will be retained. However
- * this does invalidate the CRC and will force a config
- * download every time until the configuration is updated.
- */
- if (cfg_data->size < object->size) {
- dev_err(dev, "Warning: zeroing %d byte(s) in T%d\n",
- object->size - cfg_data->size, cfg_data->type);
-
- for (i = cfg_data->size + 1; i < object->size; i++) {
- ret = mxt_write_mem(data, reg + i, 1, &val);
- if (ret)
- return ret;
- }
- }
- }
- dev_info(dev, "Updated configuration\n");
-
- return ret;
-}
-#endif
-
-
-static int mxt_calibrate_chip(struct mxt_data *data)
-{
- u8 cal_data = 1;
- int ret = 0;
- /* send calibration command to the chip */
- ret = mxt_write_mem(data,
- data->cmd_proc + CMD_CALIBRATE_OFFSET,
- 1, &cal_data);
- if (!ret)
- dev_info(&data->client->dev, "success sending calibration cmd!!!\n");
- return ret;
-}
-
-#if TSP_INFORM_CHARGER
-static int set_charger_config(struct mxt_data *data)
-{
- struct device *dev = &data->client->dev;
- struct mxt_object *object;
- struct mxt_cfg_data *cfg_data;
- u8 i, val = 0;
- u16 reg, index;
- int ret;
-
- dev_dbg(dev, "set_charger_config data->cfg_len = %d\n", data->cfg_len);
-
- for (index = 0; index < data->cfg_len;) {
- if (index + sizeof(struct mxt_cfg_data) >= data->cfg_len) {
- dev_err(dev, "index(%d) of cfg_data exceeded total size(%d)!!\n",
- index + sizeof(struct mxt_cfg_data),
- data->cfg_len);
- return -EINVAL;
- }
-
- /* Get the info about each object */
- if (data->charging_mode)
- cfg_data = (struct mxt_cfg_data *)
- (&data->ta_cfg_raw_data[index]);
- else
- cfg_data = (struct mxt_cfg_data *)
- (&data->batt_cfg_raw_data[index]);
-
- index += sizeof(struct mxt_cfg_data) + cfg_data->size;
- if (index > data->cfg_len) {
- dev_err(dev, "index(%d) of cfg_data exceeded total size(%d) in T%d object!!\n",
- index, data->cfg_len, cfg_data->type);
- return -EINVAL;
- }
-
- object = mxt_get_object(data, cfg_data->type);
- if (!object) {
- dev_err(dev, "T%d is Invalid object type\n",
- cfg_data->type);
- return -EINVAL;
- }
-
- /* Check and compare the size, instance of each object */
- if (cfg_data->size > object->size) {
- dev_err(dev, "T%d Object length exceeded!\n",
- cfg_data->type);
- return -EINVAL;
- }
- if (cfg_data->instance >= object->instances) {
- dev_err(dev, "T%d Object instances exceeded!\n",
- cfg_data->type);
- return -EINVAL;
- }
-
- dev_dbg(dev, "Writing config for obj %d len %d instance %d (%d/%d)\n",
- cfg_data->type, object->size,
- cfg_data->instance, index, data->cfg_len);
-
- reg = object->start_address + object->size * cfg_data->instance;
-
- /* Write register values of each object */
- ret = mxt_write_mem(data, reg, cfg_data->size,
- cfg_data->register_val);
- if (ret) {
- dev_err(dev, "Write T%d Object failed\n",
- object->object_type);
- return ret;
- }
-
- /*
- * If firmware is upgraded, new bytes may be added to end of
- * objects. It is generally forward compatible to zero these
- * bytes - previous behaviour will be retained. However
- * this does invalidate the CRC and will force a config
- * download every time until the configuration is updated.
- */
- if (cfg_data->size < object->size) {
- dev_err(dev, "Warning: zeroing %d byte(s) in T%d\n",
- object->size - cfg_data->size, cfg_data->type);
-
- for (i = cfg_data->size + 1; i < object->size; i++) {
- ret = mxt_write_mem(data, reg + i, 1, &val);
- if (ret)
- return ret;
- }
- }
- }
-
- return ret;
-}
-
-static void inform_charger(struct mxt_callbacks *cb,
- bool en)
-{
- struct mxt_data *data = container_of(cb,
- struct mxt_data, callbacks);
-
- cancel_delayed_work_sync(&data->noti_dwork);
- data->charging_mode = en;
- schedule_delayed_work(&data->noti_dwork, HZ / 5);
-}
-
-static void charger_noti_dwork(struct work_struct *work)
-{
- struct mxt_data *data =
- container_of(work, struct mxt_data,
- noti_dwork.work);
-
- if (!data->mxt_enabled) {
- schedule_delayed_work(&data->noti_dwork, HZ / 5);
- return ;
- }
-
- dev_info(&data->client->dev,
- "%s mode\n",
- data->charging_mode ? "charging" : "battery");
-
- set_charger_config(data);
-}
-
-static void inform_charger_init(struct mxt_data *data)
-{
- INIT_DELAYED_WORK(&data->noti_dwork, charger_noti_dwork);
-}
-#endif
-
-static void mxt_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].w);
- input_report_abs(data->input_dev, ABS_MT_PRESSURE,
- data->fingers[i].z);
-#if TSP_USE_SHAPETOUCH
- input_report_abs(data->input_dev, ABS_MT_COMPONENT,
- data->fingers[i].component);
- input_report_abs(data->input_dev, ABS_MT_SUMSIZE,
- data->sumsize);
-#endif
- }
- report_count++;
-
-#if TSP_DEBUG_INFO
- if (data->fingers[i].state == MXT_STATE_PRESS)
- dev_info(&data->client->dev, "P: id[%d] X[%d],Y[%d]\n",
- i, data->fingers[i].x, data->fingers[i].y);
-#else
- if (data->fingers[i].state == MXT_STATE_PRESS)
- dev_info(&data->client->dev, "P: id[%d]\n", i);
-#endif
- else if (data->fingers[i].state == MXT_STATE_RELEASE)
- dev_info(&data->client->dev, "R: id[%d] M[%d]\n",
- i, data->fingers[i].mcount);
-
- 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 TSP_ITDEV
- if (!data->driver_paused)
-#endif
- input_sync(data->input_dev);
- }
-
-#if (TSP_USE_SHAPETOUCH || TSP_BOOSTER)
- /* all fingers are released */
- if (count == 0) {
-#if TSP_USE_SHAPETOUCH
- data->sumsize = 0;
-#endif
-#if TSP_BOOSTER
- mxt_set_dvfs_on(data, false);
-#endif
- }
-#endif
-
- data->finger_mask = 0;
-}
-
-static void mxt_treat_T6_object(struct mxt_data *data, u8 *msg)
-{
- /* normal mode */
- if (msg[1] == 0x00)
- dev_info(&data->client->dev, "normal mode\n");
- /* I2C checksum error */
- if (msg[1] & 0x04)
- dev_err(&data->client->dev, "I2C checksum error\n");
- /* config error */
- if (msg[1] & 0x08)
- dev_err(&data->client->dev, "config error\n");
- /* calibration */
- if (msg[1] & 0x10)
- dev_info(&data->client->dev, "calibration is on going !!\n");
- /* signal error */
- if (msg[1] & 0x20)
- dev_err(&data->client->dev, "signal error\n");
- /* overflow */
- if (msg[1] & 0x40)
- dev_err(&data->client->dev, "overflow detected\n");
- /* reset */
- if (msg[1] & 0x80) {
- dev_info(&data->client->dev, "reset is ongoing\n");
-#if TSP_INFORM_CHARGER
- if (data->charging_mode)
- set_charger_config(data);
-#endif
-#if TSP_SEC_SYSFS
- data->sysfs_data->current_crc = msg[2]
- | (msg[3] << 8) | (msg[4] << 16);
- dev_dbg(&data->client->dev, "CRC [0x%06X]\n",
- data->sysfs_data->current_crc);
-#endif
- }
-}
-
-static void mxt_treat_T9_object(struct mxt_data *data, u8 *msg)
-{
- int id;
-
- id = msg[0] - data->finger_report_id;
-
- /* If not a touch event, return */
- if (id < 0 || id >= data->num_fingers)
- return;
-
- if (msg[1] & RELEASE_MSG_MASK) {
- data->fingers[id].z = 0;
- data->fingers[id].w = msg[5];
- data->fingers[id].state = MXT_STATE_RELEASE;
- mxt_report_input_data(data);
- } else if ((msg[1] & DETECT_MSG_MASK)
- && (msg[1] & (PRESS_MSG_MASK | MOVE_MSG_MASK))) {
- 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);
-
-#if TSP_USE_SHAPETOUCH
- data->fingers[id].component = msg[7];
-#endif
- 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;
- }
-
-#if TSP_BOOSTER
- mxt_set_dvfs_on(data, true);
-#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 and vector messsage */
- if (!((msg[1] & DETECT_MSG_MASK)
- && (msg[1] & AMPLITUDE_MSG_MASK
- || msg[1] & VECTOR_MSG_MASK)))
- dev_err(&data->client->dev, "Unknown state %#02x %#02x\n",
- msg[0], msg[1]);
- }
-}
-
-static void mxt_treat_T42_object(struct mxt_data *data, u8 *msg)
-{
- if (msg[1] & 0x01)
- /* Palm Press */
- dev_info(&data->client->dev, "palm touch detected\n");
- else
- /* Palm release */
- dev_info(&data->client->dev, "palm touch released\n");
-}
-
-static void mxt_treat_T57_object(struct mxt_data *data, u8 *msg)
-{
-#if TSP_USE_SHAPETOUCH
- data->sumsize = msg[1] + (msg[2] << 8);
-#endif /* TSP_USE_SHAPETOUCH */
-
-}
-static irqreturn_t mxt_irq_thread(int irq, void *ptr)
-{
- struct mxt_data *data = ptr;
- u8 msg[data->msg_object_size];
- u8 object_type, instance;
-
- do {
- if (mxt_read_mem(data, data->msg_proc, sizeof(msg), msg))
- return IRQ_HANDLED;
-
-#if TSP_ITDEV
- if (data->debug_enabled)
- print_hex_dump(KERN_INFO, "MXT MSG:",
- DUMP_PREFIX_NONE, 16, 1,
- msg, sizeof(msg), false);
-#endif /* TSP_ITDEV */
- object_type = mxt_reportid_to_type(data, msg[0] , &instance);
-
- if (object_type == RESERVED_T0)
- continue;
-
- switch (object_type) {
- case GEN_COMMANDPROCESSOR_T6:
- mxt_treat_T6_object(data, msg);
- break;
- case TOUCH_MULTITOUCHSCREEN_T9:
- mxt_treat_T9_object(data, msg);
- break;
- case PROCI_TOUCHSUPPRESSION_T42:
- mxt_treat_T42_object(data, msg);
- break;
-
- case PROCI_EXTRATOUCHSCREENDATA_T57:
- mxt_treat_T57_object(data, msg);
- break;
- default:
- dev_err(&data->client->dev,
- "Untreated Object type[%d]\tmessage[0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x]\n",
- object_type, msg[0], msg[1], msg[2],
- msg[3], msg[4], msg[5], msg[6], msg[7], msg[8]);
- break;
- }
- } while (!gpio_get_value(data->pdata->gpio_read_done));
-
- if (data->finger_mask)
- mxt_report_input_data(data);
-
- return IRQ_HANDLED;
-}
-
-/* This API should be deleted later */
-/* dummy API for cypress touchkey */
-int get_tsp_status(void)
-{
- return 0;
-}
-EXPORT_SYMBOL(get_tsp_status);
-
-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)
- mxt_report_input_data(data);
-
-#if TSP_BOOSTER
- mxt_set_dvfs_on(data, false);
-#endif
-
- data->pdata->power_off();
-
- return 0;
-}
-
-static int mxt_internal_resume(struct mxt_data *data)
-{
- struct device *dev = &data->client->dev;
- int ret;
-
- data->pdata->power_on();
-
- /* Soft reset */
- ret = mxt_reset(data);
- if (ret) {
- dev_err(dev, "Failed Reset IC\n");
- goto out;
- }
- msleep(MXT_540S_SW_RESET_TIME);
-
-out:
- return ret;
-}
-
-static int mxt_get_bootloader_version(struct i2c_client *client, u8 val)
-{
- u8 buf[3];
-
- if (val & MXT_BOOT_EXTENDED_ID) {
- if (i2c_master_recv(client, buf, sizeof(buf)) != sizeof(buf)) {
- dev_err(&client->dev, "%s: i2c recv failed\n",
- __func__);
- return -EIO;
- }
- dev_info(&client->dev, "Bootloader ID:%d Version:%d",
- buf[1], buf[2]);
- } else {
- dev_info(&client->dev, "Bootloader ID:%d",
- val & MXT_BOOT_ID_MASK);
- }
- return 0;
-}
-
-static int mxt_check_bootloader(struct i2c_client *client,
- unsigned int state)
-{
- u8 val;
-
-recheck:
- if (i2c_master_recv(client, &val, 1) != 1) {
- dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
- return -EIO;
- }
-
- switch (state) {
- case MXT_WAITING_BOOTLOAD_CMD:
- if (mxt_get_bootloader_version(client, val))
- return -EIO;
- val &= ~MXT_BOOT_STATUS_MASK;
- break;
- case MXT_WAITING_FRAME_DATA:
- case MXT_APP_CRC_FAIL:
- val &= ~MXT_BOOT_STATUS_MASK;
- break;
- case MXT_FRAME_CRC_PASS:
- if (val == MXT_FRAME_CRC_CHECK)
- goto recheck;
- if (val == MXT_FRAME_CRC_FAIL) {
- dev_err(&client->dev, "Bootloader CRC fail\n");
- return -EINVAL;
- }
- break;
- default:
- return -EINVAL;
- }
-
- if (val != state) {
- dev_err(&client->dev,
- "Invalid bootloader mode state 0x%X\n", val);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int mxt_unlock_bootloader(struct i2c_client *client)
-{
- u8 buf[2] = {MXT_UNLOCK_CMD_LSB, MXT_UNLOCK_CMD_MSB};
-
- if (i2c_master_send(client, buf, 2) != 2) {
- dev_err(&client->dev, "%s: i2c send failed\n", __func__);
-
- return -EIO;
- }
-
- return 0;
-}
-
-static int mxt_probe_bootloader(struct i2c_client *client)
-{
- u8 val;
-
- if (i2c_master_recv(client, &val, 1) != 1) {
- dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
- return -EIO;
- }
-
- if (val & (~MXT_BOOT_STATUS_MASK)) {
- if (val & MXT_APP_CRC_FAIL)
- dev_err(&client->dev, "Application CRC failure\n");
- else
- dev_err(&client->dev, "Device in bootloader mode\n");
- } else {
- dev_err(&client->dev, "%s: Unknow status\n", __func__);
- return -EIO;
- }
- return 0;
-}
-
-static int mxt_fw_write(struct i2c_client *client,
- const u8 *frame_data, unsigned int frame_size)
-{
- if (i2c_master_send(client, frame_data, frame_size) != frame_size) {
- dev_err(&client->dev, "%s: i2c send failed\n", __func__);
- return -EIO;
- }
-
- return 0;
-}
-
-#if DUAL_CFG
-int mxt_verify_fw(struct mxt_fw_info *fw_info, const struct firmware *fw)
-{
- struct mxt_data *data = fw_info->data;
- struct device *dev = &data->client->dev;
- struct mxt_fw_image *fw_img;
-
- if (!fw) {
- dev_err(dev, "could not find firmware file\n");
- return -ENOENT;
- }
-
- fw_img = (struct mxt_fw_image *)fw->data;
-
- if (le32_to_cpu(fw_img->magic_code) != MXT_FW_MAGIC) {
- /* In case, firmware file only consist of firmware */
- dev_info(dev, "Firmware file only consist of raw firmware\n");
- fw_info->fw_len = fw->size;
- fw_info->fw_raw_data = fw->data;
- } else {
- /*
- * In case, firmware file consist of header,
- * configuration, firmware.
- */
- dev_info(dev, "Firmware file consist of header, configuration, firmware\n");
- fw_info->fw_ver = fw_img->fw_ver;
- fw_info->build_ver = fw_img->build_ver;
- fw_info->hdr_len = le32_to_cpu(fw_img->hdr_len);
- fw_info->cfg_len = le32_to_cpu(fw_img->cfg_len);
- fw_info->fw_len = le32_to_cpu(fw_img->fw_len);
- fw_info->cfg_crc = le32_to_cpu(fw_img->cfg_crc);
-
- /* Check the firmware file with header */
- if (fw_info->hdr_len != sizeof(struct mxt_fw_image)
- || fw_info->hdr_len + fw_info->cfg_len
- + fw_info->fw_len != fw->size) {
- dev_err(dev, "Firmware file is invaild !!hdr size[%d] cfg,fw size[%d,%d] filesize[%d]\n",
- fw_info->hdr_len, fw_info->cfg_len,
- fw_info->fw_len, fw->size);
- return -EINVAL;
- }
-
- if (!fw_info->cfg_len) {
- dev_err(dev, "Firmware file dose not include configuration data\n");
- return -EINVAL;
- }
- if (!fw_info->fw_len) {
- dev_err(dev, "Firmware file dose not include raw firmware data\n");
- return -EINVAL;
- }
-
- /* Get the address of configuration data */
- data->cfg_len = fw_info->cfg_len / 2;
- data->batt_cfg_raw_data = fw_info->batt_cfg_raw_data
- = fw_img->data;
- data->ta_cfg_raw_data = fw_info->ta_cfg_raw_data
- = fw_img->data + (fw_info->cfg_len / 2) ;
-
- /* Get the address of firmware data */
- fw_info->fw_raw_data = fw_img->data + fw_info->cfg_len;
-
-#if TSP_SEC_SYSFS
- data->sysfs_data->fw_ver = fw_info->fw_ver;
- data->sysfs_data->build_ver = fw_info->build_ver;
-#endif
- }
-
- return 0;
-}
-#else
-int mxt_verify_fw(struct mxt_fw_info *fw_info, const struct firmware *fw)
-{
- struct mxt_data *data = fw_info->data;
- struct device *dev = &data->client->dev;
- struct mxt_fw_image *fw_img;
-
- if (!fw) {
- dev_err(dev, "could not find firmware file\n");
- return -ENOENT;
- }
-
- fw_img = (struct mxt_fw_image *)fw->data;
-
- if (le32_to_cpu(fw_img->magic_code) != MXT_FW_MAGIC) {
- /* In case, firmware file only consist of firmware */
- dev_dbg(dev, "Firmware file only consist of raw firmware\n");
- fw_info->fw_len = fw->size;
- fw_info->fw_raw_data = fw->data;
- } else {
- /*
- * In case, firmware file consist of header,
- * configuration, firmware.
- */
- dev_dbg(dev, "Firmware file consist of header, configuration, firmware\n");
- fw_info->fw_ver = fw_img->fw_ver;
- fw_info->build_ver = fw_img->build_ver;
- fw_info->hdr_len = le32_to_cpu(fw_img->hdr_len);
- fw_info->cfg_len = le32_to_cpu(fw_img->cfg_len);
- fw_info->fw_len = le32_to_cpu(fw_img->fw_len);
- fw_info->cfg_crc = le32_to_cpu(fw_img->cfg_crc);
-
- /* Check the firmware file with header */
- if (fw_info->hdr_len != sizeof(struct mxt_fw_image)
- || fw_info->hdr_len + fw_info->cfg_len
- + fw_info->fw_len != fw->size) {
- dev_err(dev, "Firmware file is invaild !!hdr size[%d] cfg,fw size[%d,%d] filesize[%d]\n",
- fw_info->hdr_len, fw_info->cfg_len,
- fw_info->fw_len, fw->size);
- return -EINVAL;
- }
-
- if (!fw_info->cfg_len) {
- dev_err(dev, "Firmware file dose not include configuration data\n");
- return -EINVAL;
- }
- if (!fw_info->fw_len) {
- dev_err(dev, "Firmware file dose not include raw firmware data\n");
- return -EINVAL;
- }
-
- /* Get the address of configuration data */
- fw_info->cfg_raw_data = fw_img->data;
-
- /* Get the address of firmware data */
- fw_info->fw_raw_data = fw_img->data + fw_info->cfg_len;
-
-#if TSP_SEC_SYSFS
- data->sysfs_data->fw_ver = fw_info->fw_ver;
- data->sysfs_data->build_ver = fw_info->build_ver;
-#endif
- }
-
- return 0;
-}
-#endif
-
-static int mxt_flash_fw(struct mxt_fw_info *fw_info)
-{
- struct mxt_data *data = fw_info->data;
- struct i2c_client *client = data->client_boot;
- struct device *dev = &data->client->dev;
- const u8 *fw_data = fw_info->fw_raw_data;
- size_t fw_size = fw_info->fw_len;
- unsigned int frame_size;
- unsigned int pos = 0;
- int ret;
-
- if (!fw_data) {
- dev_err(dev, "firmware data is Null\n");
- return -ENOMEM;
- }
-
- ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
- if (ret) {
- /*may still be unlocked from previous update attempt */
- ret = mxt_check_bootloader(client, MXT_WAITING_FRAME_DATA);
- if (ret)
- goto out;
- } else {
- dev_info(dev, "Unlocking bootloader\n");
- /* Unlock bootloader */
- mxt_unlock_bootloader(client);
- }
- while (pos < fw_size) {
- ret = mxt_check_bootloader(client,
- MXT_WAITING_FRAME_DATA);
- if (ret) {
- dev_err(dev, "Fail updating firmware. wating_frame_data err\n");
- goto out;
- }
-
- 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) {
- dev_err(dev, "Fail updating firmware. frame_crc err\n");
- goto out;
- }
-
- pos += frame_size;
-
- dev_dbg(dev, "Updated %d bytes / %zd bytes\n",
- pos, fw_size);
-
- msleep(20);
- }
- dev_info(dev, "success updating firmware\n");
-
- msleep(MXT_540S_FW_RESET_TIME);
-out:
- return ret;
-}
-
-int mxt_initialize(struct mxt_data *data)
-{
- struct i2c_client *client = data->client;
-
- u32 read_info_crc, calc_info_crc;
- int ret;
-
- ret = mxt_get_id_info(data);
- if (ret)
- return ret;
-
- data->objects = kcalloc(data->info.object_num,
- sizeof(*data->objects),
- GFP_KERNEL);
- if (!data->objects) {
- dev_err(&client->dev, "Failed to allocate memory\n");
- ret = -ENOMEM;
- goto out;
- }
-
- /* Get object table */
- ret = mxt_get_object_table(data);
- if (ret)
- goto out;
-
- data->rid_map = kcalloc(data->max_report_id + 1,
- sizeof(*data->rid_map),
- GFP_KERNEL);
-
- if (!data->rid_map) {
- dev_err(&client->dev, "Failed to allocate memory\n");
- ret = -ENOMEM;
- goto out;
- }
-
- /* Make report id table */
- mxt_make_reportid_table(data);
-
- /* Verify the info CRC */
- ret = mxt_read_info_crc(data, &read_info_crc);
- if (ret)
- goto out;
-
- ret = mxt_calculate_infoblock_crc(data, &calc_info_crc);
- if (ret)
- goto out;
-
- if (read_info_crc != calc_info_crc) {
- dev_err(&data->client->dev, "CRC error :[CRC 0x%06X!=0x%06X]\n",
- read_info_crc, calc_info_crc);
- ret = -EFAULT;
- goto out;
- }
- return 0;
-
-out:
- return ret;
-}
-
-static void mxt_handle_init_data(struct mxt_data *data)
-{
- const struct mxt_platform_data *pdata = data->pdata;
- int ret;
- u8 val;
-
- /* Set touchscreen resolution */
- mxt_write_object(data, TOUCH_MULTITOUCHSCREEN_T9,
- MXT_T9_XRANGE_LSB, (pdata->max_x) & 0xff);
- mxt_write_object(data, TOUCH_MULTITOUCHSCREEN_T9,
- MXT_T9_XRANGE_MSB, (pdata->max_x) >> 8);
- mxt_write_object(data, TOUCH_MULTITOUCHSCREEN_T9,
- MXT_T9_YRANGE_LSB, (pdata->max_y) & 0xff);
- mxt_write_object(data, TOUCH_MULTITOUCHSCREEN_T9,
- MXT_T9_YRANGE_MSB, (pdata->max_y) >> 8);
-
- /* Get acquistion time */
- ret = mxt_read_object(data, TOUCH_MULTITOUCHSCREEN_T9,
- MXT_T9_CTRL, &val);
-
- if (ret)
- data->tsp_ctrl = 0x83;
- else
- data->tsp_ctrl = (val > 0) ? val : 0x83;
-
- dev_info(&data->client->dev, "T9 CTRL : %d", data->tsp_ctrl);
-}
-
-int mxt_rest_initialize(struct mxt_fw_info *fw_info)
-{
- struct mxt_data *data = fw_info->data;
- struct device *dev = &data->client->dev;
- int ret;
-
- /* Write config */
- ret = mxt_write_config(fw_info);
- if (ret) {
- dev_err(dev, "Failed to write config from file\n");
- goto out;
- }
-
- /* Handle data for init */
- mxt_handle_init_data(data);
-
- /* Backup to memory */
- ret = mxt_backup(data);
- if (ret) {
- dev_err(dev, "Failed backup NV data\n");
- goto out;
- }
-
- /* Soft reset */
- ret = mxt_reset(data);
- if (ret) {
- dev_err(dev, "Failed Reset IC\n");
- goto out;
- }
- msleep(MXT_540S_SW_RESET_TIME);
-
-out:
- return ret;
-}
-
-static int mxt_enter_bootloader(struct mxt_data *data)
-{
- struct device *dev = &data->client->dev;
- int error;
-
- data->objects = kcalloc(data->info.object_num,
- sizeof(struct mxt_object),
- GFP_KERNEL);
- if (!data->objects) {
- dev_err(dev, "%s Failed to allocate memory\n",
- __func__);
- error = -ENOMEM;
- goto out;
- }
-
- /* Get object table information*/
- error = mxt_get_object_table(data);
- if (error)
- goto err_free_mem;
-
- /* Change to the bootloader mode */
- mxt_write_object(data, GEN_COMMANDPROCESSOR_T6,
- CMD_RESET_OFFSET, MXT_BOOT_VALUE);
-
- msleep(MXT_540S_SW_RESET_TIME);
-
-err_free_mem:
- kfree(data->objects);
- data->objects = NULL;
-
-out:
- return error;
-}
-
-static int mxt_flash_fw_on_probe(struct mxt_fw_info *fw_info)
-{
- struct mxt_data *data = fw_info->data;
- struct device *dev = &data->client->dev;
- int error;
-
- error = mxt_get_id_info(data);
- if (error) {
- /* need to check IC is in boot mode */
- error = mxt_probe_bootloader(data->client_boot);
- if (error) {
- dev_err(dev, "Failed to verify bootloader's status\n");
- goto out;
- }
-
- dev_info(dev, "Updating firmware from boot-mode\n");
- goto load_fw;
- }
-
- /* compare the version to verify necessity of firmware updating */
- if (data->info.version == fw_info->fw_ver
- && data->info.build == fw_info->build_ver) {
- dev_dbg(dev, "Firmware version is same with in IC\n");
- goto out;
- }
-
- dev_info(dev, "Updating firmware from app-mode : IC:0x%x,0x%x =! FW:0x%x,0x%x\n",
- data->info.version, data->info.build,
- fw_info->fw_ver, fw_info->build_ver);
-
- error = mxt_enter_bootloader(data);
- if (error) {
- dev_err(dev, "Failed updating firmware\n");
- goto out;
- }
-
-load_fw:
- error = mxt_flash_fw(fw_info);
- if (error)
- dev_err(dev, "Failed updating firmware\n");
- else
- dev_info(dev, "succeeded updating firmware\n");
-out:
- return error;
-}
-
-static int mxt_touch_finish_init(struct mxt_data *data)
-{
- struct i2c_client *client = data->client;
- int error;
-
- error = request_threaded_irq(client->irq, NULL, mxt_irq_thread,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT, "mxt_ts", data);
-
- if (error) {
- dev_err(&client->dev, "Failed to register interrupt\n");
- goto err_req_irq;
- }
-
-#if TSP_BOOSTER
- error = mxt_init_dvfs(data);
- if (error < 0) {
- dev_err(&client->dev, "Fail get dvfs level for touch booster\n");
- goto err_req_irq;
- }
-#endif
-
- /*
- * to prevent unnecessary report of touch event
- * it will be enabled in open function
- */
- mxt_stop(data);
-
- dev_info(&client->dev, "Mxt touch controller initialized\n");
-
- /* for blocking to be excuted open function untile finishing ts init */
- complete_all(&data->init_done);
- return 0;
-
-err_req_irq:
- return error;
-}
-
-static int mxt_touch_rest_init(struct mxt_fw_info *fw_info)
-{
- struct mxt_data *data = fw_info->data;
- struct device *dev = &data->client->dev;
- int error;
-
- error = mxt_initialize(data);
- if (error) {
- dev_err(dev, "Failed to initialize\n");
- goto err_free_mem;
- }
-
- error = mxt_rest_initialize(fw_info);
- if (error) {
- dev_err(dev, "Failed to rest initialize\n");
- goto err_free_mem;
- }
-
- error = mxt_touch_finish_init(data);
- if (error)
- goto err_free_mem;
-
- return 0;
-
-err_free_mem:
- kfree(data->objects);
- data->objects = NULL;
- kfree(data->rid_map);
- data->rid_map = NULL;
- return error;
-}
-
-
-static void mxt_request_firmware_work(const struct firmware *fw,
- void *context)
-{
- struct mxt_data *data = context;
- struct mxt_fw_info fw_info;
- int error;
-
- memset(&fw_info, 0, sizeof(struct mxt_fw_info));
- fw_info.data = data;
-
- error = mxt_verify_fw(&fw_info, fw);
- if (error)
- goto ts_rest_init;
-
- /* Skip update on boot up if firmware file does not have a header */
- if (!fw_info.hdr_len)
- goto ts_rest_init;
-
- error = mxt_flash_fw_on_probe(&fw_info);
- if (error)
- goto out;
-
-ts_rest_init:
- error = mxt_touch_rest_init(&fw_info);
-out:
- if (error)
- /* complete anyway, so open() doesn't get blocked */
- complete_all(&data->init_done);
-
- release_firmware(fw);
-}
-
-static int __devinit mxt_touch_init(struct mxt_data *data, bool nowait)
-{
- struct i2c_client *client = data->client;
- const char *firmware_name = data->pdata->firmware_name ?: MXT_FW_NAME;
- int ret = 0;
-
- data->pdata->power_on();
-
- if (nowait) {
- const struct firmware *fw;
- ret = request_firmware(&fw, firmware_name, &client->dev);
- if (ret) {
- dev_err(&client->dev,
- "error requesting built-in firmware\n");
- goto out;
- }
- mxt_request_firmware_work(fw, data);
- } else {
- ret = request_firmware_nowait(THIS_MODULE, true, firmware_name,
- &client->dev, GFP_KERNEL,
- data, mxt_request_firmware_work);
- if (ret)
- dev_err(&client->dev,
- "cannot schedule firmware update (%d)\n", ret);
- }
-
-out:
- return ret;
-}
-
-static int mxt_input_open(struct input_dev *dev)
-{
- struct mxt_data *data = input_get_drvdata(dev);
- int ret;
-
- ret = wait_for_completion_interruptible_timeout(&data->init_done,
- msecs_to_jiffies(90 * MSEC_PER_SEC));
-
- if (ret < 0) {
- dev_err(&dev->dev,
- "error while waiting for device to init (%d)\n", ret);
- ret = -ENXIO;
- goto err_open;
- }
- if (ret == 0) {
- dev_err(&dev->dev,
- "timedout while waiting for device to init\n");
- ret = -ENXIO;
- goto err_open;
- }
- data->pdata->power_reset();
-
- ret = mxt_start(data);
- if (ret)
- goto err_open;
-
- return 0;
-
-err_open:
- return ret;
-}
-
-static void mxt_input_close(struct input_dev *dev)
-{
- struct mxt_data *data = input_get_drvdata(dev);
-
- mxt_stop(data);
-}
-
-#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 TSP_INFORM_CHARGER
- cancel_delayed_work_sync(&data->noti_dwork);
-#endif
-
- mutex_lock(&data->lock);
-
- if (data->mxt_enabled) {
- disable_irq(data->client->irq);
- data->mxt_enabled = false;
- mxt_internal_suspend(data);
- } else {
- dev_err(&data->client->dev,
- "%s. but touch already off\n", __func__);
- }
-
- mutex_unlock(&data->lock);
-}
-
-static void mxt_late_resume(struct early_suspend *h)
-{
- struct mxt_data *data = container_of(h, struct mxt_data,
- early_suspend);
- mutex_lock(&data->lock);
-
- if (data->mxt_enabled) {
- dev_err(&data->client->dev,
- "%s. but touch already on\n", __func__);
- } else {
- mxt_internal_resume(data);
- data->mxt_enabled = true;
- enable_irq(data->client->irq);
- }
-
- mutex_unlock(&data->lock);
-}
-#else
-static int mxt_suspend(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct mxt_data *data = i2c_get_clientdata(client);
-
- mutex_lock(&data->lock);
-
- disable_irq(data->client->irq);
- mxt_internal_suspend(data);
- data->mxt_enabled = false;
-
- mutex_unlock(&data->lock);
- return 0;
-}
-
-static int mxt_resume(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct mxt_data *data = i2c_get_clientdata(client);
-
- mutex_lock(&data->lock);
-
- mxt_internal_resume(data);
- data->mxt_enabled = true;
- enable_irq(data->client->irq);
-
- mutex_unlock(&data->lock);
- return 0;
-}
-#endif
-
-/* Added for samsung dependency codes such as Factory test,
- * Touch booster, Related debug sysfs.
- */
-#include "mxt540s_sec.c"
-
-static int __devinit mxt_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- const struct mxt_platform_data *pdata = client->dev.platform_data;
- struct mxt_data *data;
- struct input_dev *input_dev;
- u16 boot_address;
- int i, ret = 0;
-
- if (!pdata) {
- dev_err(&client->dev, "missing platform data\n");
- return -ENODEV;
- }
-
- if (pdata->max_finger_touches <= 0)
- return -EINVAL;
-
- data = kzalloc(sizeof(*data) + pdata->max_finger_touches *
- sizeof(*data->fingers), GFP_KERNEL);
- input_dev = input_allocate_device();
- if (!data || !input_dev) {
- ret = -ENOMEM;
- dev_err(&client->dev, "input device allocation failed\n");
- goto err_alloc_dev;
- }
-
- data->client = client;
- data->input_dev = input_dev;
- data->pdata = pdata;
- data->num_fingers = pdata->max_finger_touches;
- data->mxt_enabled = true;
- mutex_init(&data->lock);
- init_completion(&data->init_done);
-
- input_dev->name = "sec_touchscreen";
- input_dev->id.bustype = BUS_I2C;
- input_dev->dev.parent = &client->dev;
- input_dev->open = mxt_input_open;
- input_dev->close = mxt_input_close;
-
- set_bit(EV_ABS, input_dev->evbit);
- set_bit(EV_KEY, input_dev->evbit);
- set_bit(MT_TOOL_FINGER, input_dev->keybit);
- set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
-
- input_mt_init_slots(input_dev, data->num_fingers);
-
- input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->min_x,
- pdata->max_x, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->min_y,
- pdata->max_y, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, pdata->min_w,
- pdata->max_w, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_PRESSURE, pdata->min_z,
- pdata->max_z, 0, 0);
-
-#if TSP_USE_SHAPETOUCH
- input_set_abs_params(input_dev, ABS_MT_COMPONENT, 0, 255, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_SUMSIZE, 0, 16 * 26, 0, 0);
-#endif
- for (i = 0; i < data->num_fingers; i++)
- data->fingers[i].state = MXT_STATE_INACTIVE;
-
- input_set_drvdata(input_dev, data);
- i2c_set_clientdata(client, data);
-
- /* regist dummy device for boot_address */
- if (data->pdata->boot_address) {
- boot_address = data->pdata->boot_address;
- } else {
- if (client->addr == MXT_APP_LOW)
- boot_address = MXT_BOOT_LOW;
- else
- boot_address = MXT_BOOT_HIGH;
- }
- data->client_boot = i2c_new_dummy(client->adapter, boot_address);
- if (!data->client_boot) {
- dev_err(&client->dev, "Fail to register sub client[0x%x]\n",
- boot_address);
- goto err_alloc_dev;
- }
-
- /* regist input device */
- ret = input_register_device(input_dev);
- if (ret)
- goto err_reg_dev;
-
-#if TSP_INFORM_CHARGER
- /* Register callbacks */
- /* To inform tsp , charger connection status*/
- data->callbacks.inform_charger = inform_charger;
- if (pdata->register_cb) {
- pdata->register_cb(&data->callbacks);
- inform_charger_init(data);
- }
-#endif
-
- ret = mxt_sysfs_init(client);
- if (ret < 0) {
- dev_err(&client->dev, "Failed to creat sysfs\n");
- goto err_init_drv;
- }
-
- ret = mxt_touch_init(data, false);
- if (ret) {
- dev_err(&client->dev, "Failed to init driver\n");
- goto err_init_drv;
- }
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
- data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
- data->early_suspend.suspend = mxt_early_suspend;
- data->early_suspend.resume = mxt_late_resume;
- register_early_suspend(&data->early_suspend);
-#endif
-
- return 0;
-
-err_init_drv:
- input_unregister_device(input_dev);
- input_dev = NULL;
- gpio_free(data->pdata->gpio_read_done);
- data->pdata->power_off();
-err_reg_dev:
- input_free_device(input_dev);
- i2c_unregister_device(data->client_boot);
-err_alloc_dev:
- kfree(data);
-
- return ret;
-}
-
-static int __devexit mxt_remove(struct i2c_client *client)
-{
- struct mxt_data *data = i2c_get_clientdata(client);
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
- unregister_early_suspend(&data->early_suspend);
-#endif
- free_irq(client->irq, data);
- kfree(data->objects);
- kfree(data->rid_map);
- gpio_free(data->pdata->gpio_read_done);
- data->pdata->power_off();
- input_unregister_device(data->input_dev);
- i2c_unregister_device(data->client_boot);
- kfree(data);
-
- return 0;
-}
-
-static struct i2c_device_id mxt_idtable[] = {
- {MXT_DEV_NAME, 0},
- {},
-};
-
-MODULE_DEVICE_TABLE(i2c, mxt_idtable);
-
-static const struct dev_pm_ops mxt_pm_ops = {
- .suspend = mxt_suspend,
- .resume = mxt_resume,
-};
-
-static struct i2c_driver mxt_i2c_driver = {
- .id_table = mxt_idtable,
- .probe = mxt_probe,
- .remove = __devexit_p(mxt_remove),
- .driver = {
- .owner = THIS_MODULE,
- .name = MXT_DEV_NAME,
-#ifdef CONFIG_PM
- .pm = &mxt_pm_ops,
-#endif
- },
-};
-
-static int __init mxt_init(void)
-{
- return i2c_add_driver(&mxt_i2c_driver);
-}
-
-static void __exit mxt_exit(void)
-{
- i2c_del_driver(&mxt_i2c_driver);
-}
-module_init(mxt_init);
-module_exit(mxt_exit);
-
-MODULE_DESCRIPTION("Atmel MaXTouch driver");
-MODULE_AUTHOR("bumwoo.lee<bw365.lee@samsung.com>");
-MODULE_LICENSE("GPL");