sec_mmi: restore internal access to sec device

Samsung LSI has tool accessing touch IC information via bunch
of function provided by sec device. This function was temporarily
unavailable to simplify bringup.

Change-Id: I9eb29f0ed8a52126df0a5dcfecf0d26dd5d7f5cc
Signed-off-by: Konstantin Makariev <hcv867@motorola.com>
Reviewed-on: https://gerrit.mot.com/1393553
SME-Granted: SME Approvals Granted
SLTApproved: Slta Waiver
Tested-by: Jira Key
Reviewed-by: Konstantin Makariev <kmakariev@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
Konstantin Makariev 2019-07-24 15:14:13 -05:00 • committed by Konstantin Makariev
commit 20b1b03bf5
10 changed files with 130 additions and 80 deletions

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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);
}

View file

@ -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;

View file

@ -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);

View file

@ -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);