diff --git a/drivers/input/touchscreen/sec_mmi/Kbuild b/drivers/input/touchscreen/sec_mmi/Kbuild index e05a7e3c662b..cd84764555d0 100644 --- a/drivers/input/touchscreen/sec_mmi/Kbuild +++ b/drivers/input/touchscreen/sec_mmi/Kbuild @@ -1,9 +1,8 @@ -# add -Wall to try to catch everything we can. -EXTRA_CFLAGS += -Wall -EXTRA_CFLAGS += \ - -I$(TOP)/motorola/kernel/modules/include \ - -I$(TOP)/motorola/kernel/modules/drivers/input/touchscreen/sec_mmi - -obj-m := sec_mmi.o -sec_mmi-objs = sec_ts.o sec_ts_fn.o sec_ts_fw.o sec_ts_mmi.o sec_cmd.o -# sec_ts_only_vendor.o +# add -Wall to try to catch everything we can. +EXTRA_CFLAGS += -Wall +EXTRA_CFLAGS += \ + -I$(TOP)/motorola/kernel/modules/include \ + -I$(TOP)/motorola/kernel/modules/drivers/input/touchscreen/sec_mmi + +obj-m := sec_mmi.o +sec_mmi-objs = sec_ts.o sec_ts_fn.o sec_ts_fw.o sec_ts_mmi.o sec_cmd.o sec_ts_only_vendor.o \ No newline at end of file diff --git a/drivers/input/touchscreen/sec_mmi/sec_cmd.c b/drivers/input/touchscreen/sec_mmi/sec_cmd.c index d856aed0cb58..5608995801bc 100644 --- a/drivers/input/touchscreen/sec_mmi/sec_cmd.c +++ b/drivers/input/touchscreen/sec_mmi/sec_cmd.c @@ -421,14 +421,14 @@ static struct attribute_group sec_fac_attr_group = { .attrs = sec_fac_attrs, }; +#ifdef CONFIG_SEC_SYSFS static inline struct device *sec_device_create(struct sec_cmd_data *data, char *dev_name) { return NULL; } static inline void sec_device_destroy(int devt) { } - -struct class *sec_class; +#endif int sec_cmd_init(struct sec_cmd_data *data, struct sec_cmd *cmds, int len, int devt) @@ -436,13 +436,6 @@ int sec_cmd_init(struct sec_cmd_data *data, struct sec_cmd *cmds, const char *dev_name; int ret, i; - sec_class = class_create(THIS_MODULE, "sec_cmd"); - ret = IS_ERR_OR_NULL(sec_class); - if (ret) { - pr_err("%s: fail - class_create\n", __func__); - return -ENODEV; - } - INIT_LIST_HEAD(&data->cmd_list_head); data->cmd_buffer_size = 0; @@ -484,7 +477,7 @@ int sec_cmd_init(struct sec_cmd_data *data, struct sec_cmd *cmds, #ifdef CONFIG_SEC_SYSFS data->fac_dev = sec_device_create(data, dev_name); #else - data->fac_dev = device_create(sec_class, NULL, devt, data, dev_name); + data->fac_dev = device_create(data->sec_class, NULL, devt, data, dev_name); #endif if (IS_ERR(data->fac_dev)) { pr_err("%s: failed to create device for the sysfs\n", __func__); @@ -506,7 +499,7 @@ err_sysfs_group: #ifdef CONFIG_SEC_SYSFS sec_device_destroy(data->fac_dev->devt); #else - device_destroy(sec_class, devt); + device_destroy(data->sec_class, devt); #endif err_sysfs_device: err_get_dev_name: @@ -533,7 +526,7 @@ void sec_cmd_exit(struct sec_cmd_data *data, int devt) #ifdef CONFIG_SEC_SYSFS sec_device_destroy(data->fac_dev->devt); #else - device_destroy(sec_class, devt); + device_destroy(data->sec_class, devt); #endif #ifdef USE_SEC_CMD_QUEUE mutex_lock(&data->fifo_lock); diff --git a/drivers/input/touchscreen/sec_mmi/sec_cmd.h b/drivers/input/touchscreen/sec_mmi/sec_cmd.h index e259c89b61e5..08132df634ea 100644 --- a/drivers/input/touchscreen/sec_mmi/sec_cmd.h +++ b/drivers/input/touchscreen/sec_mmi/sec_cmd.h @@ -64,6 +64,7 @@ struct command { #endif struct sec_cmd_data { + struct class *sec_class; struct device *fac_dev; struct list_head cmd_list_head; u8 cmd_state; diff --git a/drivers/input/touchscreen/sec_mmi/sec_mmi.h b/drivers/input/touchscreen/sec_mmi/sec_mmi.h index d20828a2207d..81162279dec8 100644 --- a/drivers/input/touchscreen/sec_mmi/sec_mmi.h +++ b/drivers/input/touchscreen/sec_mmi/sec_mmi.h @@ -23,6 +23,9 @@ struct sec_mmi_data { struct delayed_work resume_work; struct delayed_work detection_work; + atomic_t touch_stopped; + + bool force_calibration; int ctrl_dsi; unsigned int build_id; unsigned int config_id; diff --git a/drivers/input/touchscreen/sec_mmi/sec_ts.c b/drivers/input/touchscreen/sec_mmi/sec_ts.c index 018388762bb2..9684507441ef 100644 --- a/drivers/input/touchscreen/sec_mmi/sec_ts.c +++ b/drivers/input/touchscreen/sec_mmi/sec_ts.c @@ -1196,6 +1196,7 @@ static int sec_ts_parse_dt(struct i2c_client *client) input_err(true, &client->dev, "%s: Unable to request tsp_rst [%d]\n", __func__, pdata->rst_gpio); return -EINVAL; } + gpio_set_value(pdata->rst_gpio, 1); } else input_info(true, &client->dev, "%s: has no rst gpio\n", __func__); @@ -1233,10 +1234,10 @@ static int sec_ts_parse_dt(struct i2c_client *client) if (of_property_read_u32_array(np, "sec,max_coords", coords, 2)) { input_err(true, &client->dev, "%s: Failed to get max_coords property\n", __func__); - return -EINVAL; + } else { + pdata->max_x = coords[0] - 1; + pdata->max_y = coords[1] - 1; } - pdata->max_x = coords[0] - 1; - pdata->max_y = coords[1] - 1; pdata->tsp_id = of_get_named_gpio(np, "sec,tsp-id_gpio", 0); if (gpio_is_valid(pdata->tsp_id)) @@ -1573,6 +1574,26 @@ static void sec_ts_read_hw_info(struct sec_ts_data *ts) ts->fw_invalid = true; } +int sec_ts_integrity_check(struct sec_ts_data *ts) +{ + int ret = 0; + + ret = sec_ts_read_fw_info(ts); + if (ret < 0) { + input_err(true, &ts->client->dev, "%s: fail to read information 0x%x\n", __func__, ret); + return -EIO; + } + + ts->touch_functions |= SEC_TS_DEFAULT_ENABLE_BIT_SETFUNC; + ret = sec_ts_i2c_write(ts, SEC_TS_CMD_SET_TOUCHFUNCTION, (u8 *)&ts->touch_functions, 2); + if (ret < 0) + input_err(true, &ts->client->dev, "%s: Failed to send touch func_mode command", __func__); + + schedule_delayed_work(&ts->work_read_info, msecs_to_jiffies(50)); + + return 0; +} + static int sec_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct sec_ts_data *ts; @@ -1714,43 +1735,17 @@ static int sec_ts_probe(struct i2c_client *client, const struct i2c_device_id *i input_info(true, &ts->client->dev, "%s: fw update on probe disabled!\n", __func__); #endif #endif - ret = sec_ts_read_fw_info(ts); - if (ret < 0) { - input_err(true, &ts->client->dev, "%s: fail to read information 0x%x\n", __func__, ret); - goto err_init; - } - - ts->touch_functions |= SEC_TS_DEFAULT_ENABLE_BIT_SETFUNC; - ret = sec_ts_i2c_write(ts, SEC_TS_CMD_SET_TOUCHFUNCTION, (u8 *)&ts->touch_functions, 2); - if (ret < 0) - input_err(true, &ts->client->dev, "%s: Failed to send touch func_mode command", __func__); - if (ts->plat_data->support_dex) { ts->input_dev_pad->name = "sec_touchpad"; sec_ts_set_input_prop(ts, ts->input_dev_pad, INPUT_PROP_POINTER); - } - ts->dex_name = ""; - ts->input_dev->name = "sec_touchscreen"; - sec_ts_set_input_prop(ts, ts->input_dev, INPUT_PROP_DIRECT); -#ifdef USE_OPEN_CLOSE - ts->input_dev->open = sec_ts_input_open; - ts->input_dev->close = sec_ts_input_close; -#endif - ts->input_dev_touch = ts->input_dev; - - ret = input_register_device(ts->input_dev); - if (ret) { - input_err(true, &ts->client->dev, "%s: Unable to register %s input device\n", __func__, ts->input_dev->name); - goto err_input_register_device; - } - if (ts->plat_data->support_dex) { ret = input_register_device(ts->input_dev_pad); if (ret) { input_err(true, &ts->client->dev, "%s: Unable to register %s input device\n", __func__, ts->input_dev_pad->name); goto err_input_pad_register_device; } } + ts->dex_name = ""; input_info(true, &ts->client->dev, "%s: request_irq = %d\n", __func__, client->irq); @@ -1765,7 +1760,7 @@ static int sec_ts_probe(struct i2c_client *client, const struct i2c_device_id *i ts->irq_enabled = true; /* need remove below resource @ remove driver */ -#if 0 //!defined(CONFIG_SAMSUNG_PRODUCT_SHIP) +#if 1 //!defined(CONFIG_SAMSUNG_PRODUCT_SHIP) sec_ts_raw_device_init(ts); #endif sec_ts_fn_init(ts); @@ -1781,9 +1776,20 @@ static int sec_ts_probe(struct i2c_client *client, const struct i2c_device_id *i if (ret) goto err_mmi_data; - device_init_wakeup(&client->dev, true); + sec_ts_set_input_prop(ts, ts->input_dev, INPUT_PROP_DIRECT); +#ifdef USE_OPEN_CLOSE + ts->input_dev->open = sec_ts_input_open; + ts->input_dev->close = sec_ts_input_close; +#endif + ts->input_dev_touch = ts->input_dev; - schedule_delayed_work(&ts->work_read_info, msecs_to_jiffies(50)); + ret = input_register_device(ts->input_dev); + if (ret) { + input_err(true, &ts->client->dev, "%s: Unable to register %s input device\n", __func__, ts->input_dev->name); + goto err_input_register_device; + } + + device_init_wakeup(&client->dev, true); #if defined(CONFIG_TOUCHSCREEN_DUMP_MODE) dump_callbacks.inform_dump = dump_tsp_log; @@ -1807,19 +1813,17 @@ err_irq: input_unregister_device(ts->input_dev_pad); ts->input_dev_pad = NULL; } -err_input_pad_register_device: - input_unregister_device(ts->input_dev); - ts->input_dev = NULL; - ts->input_dev_touch = NULL; err_input_register_device: kfree(ts->pFrame); -err_init: wakeup_source_trash(&ts->wakelock); sec_ts_power(ts, false); if (ts->plat_data->support_dex) { if (ts->input_dev_pad) input_free_device(ts->input_dev_pad); } +err_input_pad_register_device: + ts->input_dev = NULL; + ts->input_dev_touch = NULL; err_allocate_input_dev_pad: if (ts->input_dev) input_free_device(ts->input_dev); diff --git a/drivers/input/touchscreen/sec_mmi/sec_ts.h b/drivers/input/touchscreen/sec_mmi/sec_ts.h index eb96b39da464..8ecc6a785303 100644 --- a/drivers/input/touchscreen/sec_mmi/sec_ts.h +++ b/drivers/input/touchscreen/sec_mmi/sec_ts.h @@ -815,6 +815,7 @@ void sec_ts_locked_release_all_finger(struct sec_ts_data *ts); void sec_ts_fn_remove(struct sec_ts_data *ts); void sec_ts_delay(unsigned int ms); int sec_ts_read_information(struct sec_ts_data *ts); +int sec_ts_integrity_check(struct sec_ts_data *ts); int execute_selftest(struct sec_ts_data *ts, bool save_result); void sec_ts_run_rawdata_all(struct sec_ts_data *ts, bool full_read); diff --git a/drivers/input/touchscreen/sec_mmi/sec_ts_fn.c b/drivers/input/touchscreen/sec_mmi/sec_ts_fn.c index 0a07c9830c28..ed34e9feb7aa 100644 --- a/drivers/input/touchscreen/sec_mmi/sec_ts_fn.c +++ b/drivers/input/touchscreen/sec_mmi/sec_ts_fn.c @@ -326,7 +326,10 @@ static ssize_t read_vendor_show(struct device *dev, struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); unsigned char buffer[10] = { 0 }; - snprintf(buffer, 5, ts->plat_data->firmware_name + 8); + if (ts->plat_data->firmware_name) + snprintf(buffer, 5, ts->plat_data->firmware_name + 8); + else + strlcpy(buffer, "undef", 5); return snprintf(buf, SEC_CMD_BUF_SIZE, "LSI_%s", buffer); } diff --git a/drivers/input/touchscreen/sec_mmi/sec_ts_fw.c b/drivers/input/touchscreen/sec_mmi/sec_ts_fw.c index 856cf48eda39..0ed37612f922 100644 --- a/drivers/input/touchscreen/sec_mmi/sec_ts_fw.c +++ b/drivers/input/touchscreen/sec_mmi/sec_ts_fw.c @@ -627,6 +627,7 @@ int sec_ts_firmware_update(struct sec_ts_data *ts, const u8 *data, } sec_ts_sw_reset(ts); + ts->fw_invalid = true; if (!bl_update) { if (restore_cal) { @@ -654,6 +655,7 @@ int sec_ts_firmware_update(struct sec_ts_data *ts, const u8 *data, return -EIO; } + ts->fw_invalid = false; input_info(true, &ts->client->dev, "%s: fw update Success! read_boot_status = 0x%x\n", __func__, fw_status); return 1; diff --git a/drivers/input/touchscreen/sec_mmi/sec_ts_mmi.c b/drivers/input/touchscreen/sec_mmi/sec_ts_mmi.c index 4e28da1fec18..3ed455f452c2 100644 --- a/drivers/input/touchscreen/sec_mmi/sec_ts_mmi.c +++ b/drivers/input/touchscreen/sec_mmi/sec_ts_mmi.c @@ -129,7 +129,11 @@ static int sec_mmi_touchscreen_class( struct device_attribute *attrs = class_attributes; bool unreg_class = false; int i, error = 0; + char buffer[128]; + struct sec_ts_data *ts = data->ts_ptr; + ssize_t namelen; const char *class_fname = "primary"; + static char *input_dev_name; static struct class *touchscreen_class; static int minor; @@ -168,6 +172,14 @@ static int sec_mmi_touchscreen_class( dev_set_drvdata(data->ts_class_dev, data); + /* construct input device name */ + namelen = scnprintf(buffer, sizeof(buffer), "samsung_mmi.%s", class_fname); + // FIXME namelen = scnprintf(buffer, sizeof(buffer), "synaptics_mmi.%s", class_fname); + if (namelen) { + input_dev_name = kstrdup(buffer, GFP_KERNEL); + ts->input_dev->name = input_dev_name; + } + for (i = 0; attrs[i].attr.name != NULL; ++i) { error = device_create_file(data->ts_class_dev, &attrs[i]); if (error) @@ -244,7 +256,6 @@ static void sec_mmi_fw_read_id(struct sec_mmi_data *data) "%s: failed to read fw version (%d)\n", __func__, ret); } else { - bdc2ui(&data->build_id, buffer, sizeof(data->build_id)); dev_dbg(DEV_MMI, "%s: FW VERSION: " \ "%02X, %02X, %02X, %02X, %02X, %02X, %02X, %02X\n", __func__, buffer[0], buffer[1], buffer[2], buffer[3], @@ -272,11 +283,18 @@ static void sec_mmi_fw_read_id(struct sec_mmi_data *data) "%s: failed to read fw version (%d)\n", __func__, ret); } else { + if (buffer[0] == 0x17) + ts->device_id[3] = 0x7C; + bdc2ui(&data->build_id, buffer, sizeof(data->build_id)); dev_dbg(DEV_MMI, "%s: IMAGE VER: " \ "%02X, %02X, %02X, %02X, %02X, %02X, %02X, %02X\n", __func__, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7]); } + + snprintf(data->product_id, sizeof(data->product_id), "%c%c%c%02x", + tolower(ts->device_id[0]), tolower(ts->device_id[1]), + ts->device_id[2], ts->device_id[3]); } static void sec_mmi_ic_reset(struct sec_mmi_data *data) @@ -329,7 +347,6 @@ static void sec_mmi_work(struct work_struct *w) bool panel_ready = true; char *pname = NULL; -#if defined(CONFIG_DRM) /* DRM panel status */ panel_ready = dsi_display_is_panel_enable(data->ctrl_dsi, &probe_status, &pname); @@ -343,13 +360,13 @@ static void sec_mmi_work(struct work_struct *w) dev_dbg(DEV_MMI, "%s: panel ready\n", __func__); //rmi4_data->drm_state = DRM_ST_READY; } -#endif - if (!ts->fw_invalid) { + if (ts->fw_invalid == false) { + sec_mmi_fw_read_id(data); + sec_ts_integrity_check(ts); + sec_ts_sense_on(ts); dev_dbg(DEV_MMI, "%s: sensing turned on\n", __func__); - - sec_mmi_fw_read_id(data); } } @@ -360,11 +377,27 @@ static void sec_mmi_queued_resume(struct work_struct *w) struct sec_mmi_data *data = container_of(dw, struct sec_mmi_data, resume_work); struct sec_ts_data *ts = data->ts_ptr; + unsigned char buffer = 0; + int ret; + + if (atomic_cmpxchg(&data->touch_stopped, 1, 0) == 0) + return; + + sec_mmi_ic_reset(data); + ret = ts->sec_ts_i2c_read(ts, SEC_TS_READ_BOOT_STATUS, + &buffer, sizeof(buffer)); + if (ret < 0) + dev_err(DEV_MMI, + "%s: failed to read boot status (%d)\n", + __func__, ret); + + ts->fw_invalid = buffer == SEC_TS_STATUS_BOOT_MODE; + ts->power_status = SEC_TS_STATE_POWER_ON; if (ts->lowpower_mode) complete_all(&ts->resume_done); - dev_dbg(DEV_MMI, "%s: touch resumed\n", __func__); + dev_info(DEV_MMI, "%s: touch resumed\n", __func__); } static int inline sec_mmi_display_on(struct sec_mmi_data *data) @@ -378,12 +411,17 @@ static int inline sec_mmi_display_off(struct sec_mmi_data *data) { struct sec_ts_data *ts = data->ts_ptr; - cancel_delayed_work_sync(&data->resume_work); + if (atomic_cmpxchg(&data->touch_stopped, 0, 1) == 1) + return 0; + /* complete critical work */ sec_mmi_wait4idle(data); + sec_ts_set_lowpowermode(ts, TO_LOWPOWER_MODE); + cancel_delayed_work_sync(&data->resume_work); + if (ts->lowpower_mode) reinit_completion(&ts->resume_done); - dev_dbg(DEV_MMI, "%s: touch suspended\n", __func__); + dev_info(DEV_MMI, "%s: touch suspended\n", __func__); return 0; } @@ -558,7 +596,7 @@ static ssize_t sec_mmi_reset_store(struct device *dev, { struct sec_ts_data *ts = dev_get_drvdata(dev); sec_mmi_ic_reset(ts->mmi_ptr); - return 0; + return size; } static ssize_t sec_mmi_ic_ver_show(struct device *dev, @@ -575,6 +613,9 @@ static ssize_t sec_mmi_ic_ver_show(struct device *dev, static ssize_t sec_mmi_forcereflash_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { + struct sec_ts_data *ts = dev_get_drvdata(dev); + struct sec_mmi_data *data = ts->mmi_ptr; + data->force_calibration = true; return size; } @@ -582,6 +623,7 @@ static ssize_t sec_mmi_doreflash_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct sec_ts_data *ts = dev_get_drvdata(dev); + struct sec_mmi_data *data = ts->mmi_ptr; const struct firmware *fw_entry; char fw_path[SEC_TS_MAX_FW_PATH]; int result = -EFAULT; @@ -592,22 +634,27 @@ static ssize_t sec_mmi_doreflash_store(struct device *dev, } strlcpy(fw_path, buf, size); - input_info(true, DEV_TS, "%s: update fw from %s\n", __func__, fw_path); + dev_dbg(DEV_TS, "%s: update fw from %s\n", __func__, fw_path); /* Loading Firmware------------------------------------------ */ if (request_firmware(&fw_entry, fw_path, &ts->client->dev) != 0) { - input_err(true, DEV_TS, "%s: fw not available\n", __func__); + dev_err(DEV_TS, "%s: fw not available\n", __func__); goto err_request_fw; } - input_info(true, DEV_TS, "%s: fw size = %d\n", __func__, (int)fw_entry->size); + dev_dbg(DEV_TS, "%s: fw size = %d\n", __func__, (int)fw_entry->size); mutex_lock(&ts->modechange); sec_ts_irq_enable(ts, false); __pm_stay_awake(&ts->wakelock); - result = sec_ts_firmware_update(ts, fw_entry->data, fw_entry->size, 0, false, 0); - if (result == 1) + result = sec_ts_firmware_update(ts, fw_entry->data, fw_entry->size, + 0, data->force_calibration, 0); + if (ts->fw_invalid == false) { sec_mmi_fw_read_id(ts->mmi_ptr); + sec_ts_integrity_check(ts); + } + + data->force_calibration = false; mutex_unlock(&ts->modechange); sec_ts_irq_enable(ts, true); @@ -682,10 +729,6 @@ int sec_mmi_data_init(struct sec_ts_data *ts, bool enable) return -ENODEV; } #endif - snprintf(data->product_id, sizeof(data->product_id), "%c%c%c%02x", - tolower(ts->device_id[0]), tolower(ts->device_id[1]), - ts->device_id[2], ts->device_id[3]); - INIT_DELAYED_WORK(&data->resume_work, sec_mmi_queued_resume); INIT_DELAYED_WORK(&data->detection_work, sec_mmi_work); diff --git a/drivers/input/touchscreen/sec_mmi/sec_ts_only_vendor.c b/drivers/input/touchscreen/sec_mmi/sec_ts_only_vendor.c index a1203ee74ff6..f6d8828a3104 100644 --- a/drivers/input/touchscreen/sec_mmi/sec_ts_only_vendor.c +++ b/drivers/input/touchscreen/sec_mmi/sec_ts_only_vendor.c @@ -238,7 +238,7 @@ static ssize_t sec_ts_enter_recovery_store(struct device *dev, struct device_att enable_irq(ts->client->irq); } - sec_ts_read_information(ts); + sec_ts_integrity_check(ts); return size; } @@ -274,6 +274,7 @@ int sec_ts_raw_device_init(struct sec_ts_data *ts) return ret; } + ts->sec.sec_class = sec_class; ts->dev = device_create(sec_class, NULL, 0, ts, "sec_ts"); ret = IS_ERR(ts->dev);