diff options
Diffstat (limited to 'drivers/input/touchscreen/mxt540s.c')
-rw-r--r-- | drivers/input/touchscreen/mxt540s.c | 2131 |
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, ¤t_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, ¤t_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"); |