diff options
Diffstat (limited to 'drivers/input/touchscreen/wacom/wacom_i2c.c')
-rw-r--r-- | drivers/input/touchscreen/wacom/wacom_i2c.c | 947 |
1 files changed, 681 insertions, 266 deletions
diff --git a/drivers/input/touchscreen/wacom/wacom_i2c.c b/drivers/input/touchscreen/wacom/wacom_i2c.c index a63072f..273db1b 100644 --- a/drivers/input/touchscreen/wacom/wacom_i2c.c +++ b/drivers/input/touchscreen/wacom/wacom_i2c.c @@ -26,7 +26,7 @@ #include <linux/firmware.h> #include "wacom_i2c_func.h" #include "wacom_i2c_flash.h" -#ifdef COOR_WORK_AROUND +#ifdef WACOM_IMPORT_FW_ALGO #include "wacom_i2c_coord_tables.h" #endif @@ -36,7 +36,33 @@ unsigned char screen_rotate; unsigned char user_hand = 1; static bool epen_reset_result; -static bool epen_checksum_result; + +static void wacom_i2c_enable_irq(struct wacom_i2c *wac_i2c, bool enable) +{ + static int depth; + + if (enable) { + if (depth) { + --depth; + enable_irq(wac_i2c->irq); +#ifdef WACOM_PDCT_WORK_AROUND + enable_irq(wac_i2c->irq_pdct); +#endif + } + } else { + if (!depth) { + ++depth; + disable_irq(wac_i2c->irq); +#ifdef WACOM_PDCT_WORK_AROUND + disable_irq(wac_i2c->irq_pdct); +#endif + } + } + +#ifdef WACOM_IRQ_DEBUG + printk(KERN_DEBUG"[E-PEN] Enable %d, depth %d\n", (int)enable, depth); +#endif +} static void wacom_i2c_reset_hw(struct wacom_g5_platform_data *wac_pdata) { @@ -47,27 +73,61 @@ static void wacom_i2c_reset_hw(struct wacom_g5_platform_data *wac_pdata) msleep(200); } -int wacom_i2c_load_fw(struct i2c_client *client) +static void wacom_i2c_enable(struct wacom_i2c *wac_i2c) { - struct file *fp; - mm_segment_t old_fs; - long fsize, nread; - int ret; - struct wacom_i2c *wac_i2c = i2c_get_clientdata(client); - unsigned char *Binary_UMS = NULL; + bool en = true; +#ifdef BATTERY_SAVING_MODE + if (wac_i2c->battery_saving_mode + && wac_i2c->pen_insert) + en = false; +#endif + + if (en) { + wac_i2c->wac_pdata->late_resume_platform_hw(); + schedule_delayed_work(&wac_i2c->resume_work, HZ / 5); + } +} + +static void wacom_i2c_disable(struct wacom_i2c *wac_i2c) +{ + if (wac_i2c->power_enable) { + wacom_i2c_enable_irq(wac_i2c, false); + + /* release pen, if it is pressed */ #if defined(CONFIG_MACH_P4NOTE) - Binary_UMS = kmalloc(MAX_ADDR_514 + 1, GFP_KERNEL); +#ifdef WACOM_PDCT_WORK_AROUND + if (wac_i2c->pen_pdct == PDCT_DETECT_PEN) +#else + if (wac_i2c->pen_pressed || wac_i2c->side_pressed + || wac_i2c->pen_prox) +#endif #else - Binary_UMS = kmalloc(WACOM_FW_SIZE, GFP_KERNEL); + if (wac_i2c->pen_pressed || wac_i2c->side_pressed + || wac_i2c->pen_prox) #endif + forced_release(wac_i2c); - if (Binary_UMS == NULL) { - printk(KERN_DEBUG "[E-PEN] %s, kmalloc failed\n", __func__); - return -ENOENT; + if (!wake_lock_active(&wac_i2c->wakelock)) { + wac_i2c->power_enable = false; + wac_i2c->wac_pdata->early_suspend_platform_hw(); + } } +} + +int wacom_i2c_get_ums_data(struct wacom_i2c *wac_i2c, u8 **ums_data) +{ + struct file *fp; + mm_segment_t old_fs; + long fsize, nread; + int ret = 0; + unsigned int nSize; - wacom_i2c_set_firm_data(Binary_UMS); +#if defined(CONFIG_MACH_P4NOTE) + nSize = MAX_ADDR_514 + 1; +#else + nSize = WACOM_FW_SIZE; +#endif old_fs = get_fs(); set_fs(KERNEL_DS); @@ -76,56 +136,90 @@ int wacom_i2c_load_fw(struct i2c_client *client) if (IS_ERR(fp)) { printk(KERN_ERR "[E-PEN] failed to open %s.\n", WACOM_FW_PATH); - goto open_err; + ret = -ENOENT; + set_fs(old_fs); + return ret; } fsize = fp->f_path.dentry->d_inode->i_size; - printk(KERN_NOTICE "[E-PEN] start, file path %s, size %ld Bytes\n", - WACOM_FW_PATH, fsize); + printk(KERN_NOTICE + "[E-PEN] start, file path %s, size %ld Bytes\n", + WACOM_FW_PATH, fsize); + + if (fsize != nSize) { + printk(KERN_ERR "[E-PEN] UMS firmware size is different\n"); + ret = -EFBIG; + goto size_error; + } - nread = vfs_read(fp, (char __user *)Binary, fsize, &fp->f_pos); - printk(KERN_ERR "[E-PEN] nread %ld Bytes\n", nread); - if (nread != fsize) { + *ums_data = kmalloc(fsize, GFP_KERNEL); + if (IS_ERR(*ums_data)) { printk(KERN_ERR - "[E-PEN] failed to read firmware file, nread %ld Bytes\n", - nread); - goto read_err; + "[E-PEN] %s, kmalloc failed\n", __func__); + ret = -EFAULT; + goto malloc_error; } - ret = wacom_i2c_flash(wac_i2c); - if (ret < 0) { - printk(KERN_ERR "[E-PEN] failed to write firmware(%d)\n", ret); - goto fw_write_err; + nread = vfs_read(fp, (char __user *)*ums_data, + fsize, &fp->f_pos); + printk(KERN_NOTICE "[E-PEN] nread %ld Bytes\n", nread); + if (nread != fsize) { + printk(KERN_ERR + "[E-PEN] failed to read firmware file, nread %ld Bytes\n", + nread); + ret = -EIO; + kfree(*ums_data); + goto read_err; } - wacom_i2c_set_firm_data(NULL); - - kfree(Binary_UMS); - filp_close(fp, current->files); set_fs(old_fs); return 0; - open_err: - kfree(Binary_UMS); - set_fs(old_fs); - return -ENOENT; - read_err: - kfree(Binary_UMS); + malloc_error: + size_error: filp_close(fp, current->files); + open_err: set_fs(old_fs); - return -EIO; + return ret; +} - fw_write_err: - kfree(Binary_UMS); - filp_close(fp, current->files); - set_fs(old_fs); - return -1; +int wacom_i2c_fw_update_UMS(struct i2c_client *client) +{ + int ret = 0; + struct wacom_i2c *wac_i2c = i2c_get_clientdata(client); + u8 *ums_data = NULL; + + printk(KERN_ERR "[E-PEN] Start firmware flashing (UMS).\n"); + + /*read firmware data*/ + ret = wacom_i2c_get_ums_data(wac_i2c, &ums_data); + if (ret < 0) { + printk(KERN_DEBUG"[E-PEN] file op is failed\n"); + return 0; + } + + /*start firm update*/ + wacom_i2c_set_firm_data(ums_data); + + ret = wacom_i2c_flash(wac_i2c); + if (ret < 0) { + printk(KERN_ERR + "[E-PEN] failed to write firmware(%d)\n", ret); + kfree(ums_data); + wacom_i2c_set_firm_data(NULL); + return ret; + } + + wacom_i2c_set_firm_data(NULL); + kfree(ums_data); + + return 0; } -#if defined(CONFIG_MACH_Q1_BD) +#if defined(CONFIG_MACH_Q1_BD) || defined(CONFIG_MACH_T0) int wacom_i2c_firm_update(struct wacom_i2c *wac_i2c) { int ret; @@ -165,19 +259,81 @@ int wacom_i2c_firm_update(struct wacom_i2c *wac_i2c) } #endif -static void update_work_func(struct work_struct *work) +#if defined(CONFIG_MACH_P4NOTE) +static bool epen_check_factory_mode(void) { - int ret = 0; - int retry = 2; - struct wacom_i2c *wac_i2c = - container_of(work, struct wacom_i2c, update_work); + struct file *fp; + mm_segment_t old_fs; + long fsize; + int err = 0; + int nread = 0; + char *buf; + bool ret = false; - printk(KERN_DEBUG "[E-PEN] %s\n", __func__); + old_fs = get_fs(); + set_fs(KERNEL_DS); - disable_irq(wac_i2c->irq); -#ifdef WACOM_PDCT_WORK_AROUND - disable_irq(wac_i2c->irq_pdct); -#endif + fp = filp_open("/efs/FactoryApp/factorymode", + O_RDONLY, S_IRUSR); + + if (IS_ERR(fp)) { + err = PTR_ERR(fp); + if (err == -ENOENT) + pr_err("[E-PEN] There is no file\n"); + else + pr_err("[E-PEN] File open error(%d)\n", err); + + ret = false; + goto out; + } + + fsize = fp->f_path.dentry->d_inode->i_size; + + if (!fsize) { + pr_err("[E-PEN] File size os zero\n"); + ret = false; + goto err_filesize; + } + + buf = kzalloc(fsize, GFP_KERNEL); + if (!buf) { + pr_err("[E-PEN] Memory allocate failed\n"); + ret = false; + goto err_filesize; + } + + nread = vfs_read(fp, (char __user *)buf, fsize, &fp->f_pos); + if (nread != fsize) { + pr_err("[E-PEN] File size[%ld] not same with read one[%d]\n", + fsize, nread); + ret = false; + goto err_readfail; + } + + /* + * if the factory mode is disable, + * do not update the firmware. + * factory mode : ON -> disable + * factory mode : OFF -> enable + */ + if (strncmp("ON", buf, 2)) + ret = true; + + printk(KERN_DEBUG "[E-PEN] Factorymode is %s\n", ret ? "ENG" : "USER"); + +err_readfail: + kfree(buf); +err_filesize: + filp_close(fp, current->files); +out: + set_fs(old_fs); + return ret; +} + +static void update_fw_p4(struct wacom_i2c *wac_i2c) +{ + int ret = 0; + int retry = 2; while (retry--) { printk(KERN_DEBUG "[E-PEN] INIT_FIRMWARE_FLASH is enabled.\n"); @@ -191,16 +347,10 @@ static void update_work_func(struct work_struct *work) /* Reset IC */ wacom_i2c_reset_hw(wac_i2c->wac_pdata); } - msleep(800); - printk(KERN_DEBUG "[E-PEN] flashed.(%d)\n", ret); - wacom_i2c_query(wac_i2c); - - enable_irq(wac_i2c->irq); -#ifdef WACOM_PDCT_WORK_AROUND - enable_irq(wac_i2c->irq_pdct); -#endif + printk(KERN_DEBUG "[E-PEN] flashed.(%d)\n", ret); } +#endif static irqreturn_t wacom_interrupt(int irq, void *dev_id) { @@ -214,6 +364,9 @@ static irqreturn_t wacom_interrupt_pdct(int irq, void *dev_id) { struct wacom_i2c *wac_i2c = dev_id; + if (wac_i2c->query_status == false) + return IRQ_HANDLED; + wac_i2c->pen_pdct = gpio_get_value(wac_i2c->wac_pdata->gpio_pendct); printk(KERN_DEBUG "[E-PEN] pdct %d(%d)\n", @@ -230,6 +383,89 @@ static irqreturn_t wacom_interrupt_pdct(int irq, void *dev_id) } #endif +#ifdef WACOM_PEN_DETECT + +#ifdef CONFIG_MACH_T0 +bool wacom_i2c_invert_by_switch_type(void) +{ + if (system_rev < WACOM_DETECT_SWITCH_HWID) + return true; + + return false; +} +#endif + +static void pen_insert_work(struct work_struct *work) +{ + struct wacom_i2c *wac_i2c = + container_of(work, struct wacom_i2c, pen_insert_dwork.work); + + wac_i2c->pen_insert = !gpio_get_value(wac_i2c->gpio_pen_insert); + +#if defined(CONFIG_MACH_T0) + if (wac_i2c->invert_pen_insert) + wac_i2c->pen_insert = !wac_i2c->pen_insert; +#endif + + printk(KERN_DEBUG "[E-PEN] %s : %d\n", + __func__, wac_i2c->pen_insert); + + input_report_switch(wac_i2c->input_dev, + SW_PEN_INSERT, !wac_i2c->pen_insert); + input_sync(wac_i2c->input_dev); + +#ifdef BATTERY_SAVING_MODE + if (wac_i2c->pen_insert) { + if (wac_i2c->battery_saving_mode) + wacom_i2c_disable(wac_i2c); + } else + wacom_i2c_enable(wac_i2c); +#endif +} +static irqreturn_t wacom_pen_detect(int irq, void *dev_id) +{ + struct wacom_i2c *wac_i2c = dev_id; + + cancel_delayed_work_sync(&wac_i2c->pen_insert_dwork); + schedule_delayed_work(&wac_i2c->pen_insert_dwork, HZ / 20); + return IRQ_HANDLED; +} +static int wacom_i2c_input_open(struct input_dev *dev) +{ +#ifdef WACOM_PEN_DETECT + struct wacom_i2c *wac_i2c = input_get_drvdata(dev); + int ret = 0; + int irq = gpio_to_irq(wac_i2c->gpio_pen_insert); + + INIT_DELAYED_WORK(&wac_i2c->pen_insert_dwork, pen_insert_work); + + ret = + request_threaded_irq( + irq, NULL, + wacom_pen_detect, + IRQF_DISABLED | IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "pen_insert", wac_i2c); + if (ret < 0) + printk(KERN_ERR + "[E-PEN]: failed to request pen insert irq\n"); + + enable_irq_wake(irq); + + /* update the current status */ + schedule_delayed_work(&wac_i2c->pen_insert_dwork, HZ / 2); +#endif + + return 0; +} + +static void wacom_i2c_input_close(struct input_dev *dev) +{ + /* TBD */ +} + +#endif + static void wacom_i2c_set_input_values(struct i2c_client *client, struct wacom_i2c *wac_i2c, struct input_dev *input_dev) @@ -241,6 +477,13 @@ static void wacom_i2c_set_input_values(struct i2c_client *client, input_dev->dev.parent = &client->dev; input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + input_dev->evbit[0] |= BIT_MASK(EV_SW); + input_set_capability(input_dev, EV_SW, SW_PEN_INSERT); +#ifdef WACOM_PEN_DETECT + input_dev->open = wacom_i2c_input_open; + input_dev->close = wacom_i2c_input_close; +#endif + __set_bit(ABS_X, input_dev->absbit); __set_bit(ABS_Y, input_dev->absbit); __set_bit(ABS_PRESSURE, input_dev->absbit); @@ -249,6 +492,8 @@ static void wacom_i2c_set_input_values(struct i2c_client *client, __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); __set_bit(BTN_STYLUS, input_dev->keybit); __set_bit(KEY_UNKNOWN, input_dev->keybit); + __set_bit(KEY_PEN_PDCT, input_dev->keybit); + /* __set_bit(BTN_STYLUS2, input_dev->keybit); */ /* __set_bit(ABS_MISC, input_dev->absbit); */ } @@ -275,24 +520,8 @@ static void wacom_i2c_early_suspend(struct early_suspend *h) { struct wacom_i2c *wac_i2c = container_of(h, struct wacom_i2c, early_suspend); - - disable_irq(wac_i2c->client->irq); -#ifdef WACOM_PDCT_WORK_AROUND - disable_irq(wac_i2c->irq_pdct); -#endif - - /* release pen, if it is pressed */ -#ifdef WACOM_PDCT_WORK_AROUND - if (wac_i2c->pen_pdct == PDCT_DETECT_PEN) -#else - if (wac_i2c->pen_pressed || wac_i2c->side_pressed - || wac_i2c->pen_prox) -#endif - forced_release(wac_i2c); - - if (!wake_lock_active(&wac_i2c->wakelock)) - wac_i2c->wac_pdata->early_suspend_platform_hw(); printk(KERN_DEBUG "[E-PEN] %s.\n", __func__); + wacom_i2c_disable(wac_i2c); } static void wacom_i2c_resume_work(struct work_struct *work) @@ -302,13 +531,14 @@ static void wacom_i2c_resume_work(struct work_struct *work) #if defined(WACOM_PDCT_WORK_AROUND) irq_set_irq_type(wac_i2c->irq_pdct, IRQ_TYPE_EDGE_BOTH); -#elif defined(CONFIG_MACH_P4NOTE) - irq_set_irq_type(wac_i2c->client->irq, IRQ_TYPE_EDGE_RISING); #endif - enable_irq(wac_i2c->client->irq); -#ifdef WACOM_PDCT_WORK_AROUND - enable_irq(wac_i2c->irq_pdct); + +#if defined(CONFIG_MACH_P4NOTE) + irq_set_irq_type(wac_i2c->client->irq, IRQ_TYPE_EDGE_RISING); #endif + + wac_i2c->power_enable = true; + wacom_i2c_enable_irq(wac_i2c, true); printk(KERN_DEBUG "[E-PEN] %s\n", __func__); } @@ -316,9 +546,9 @@ static void wacom_i2c_late_resume(struct early_suspend *h) { struct wacom_i2c *wac_i2c = container_of(h, struct wacom_i2c, early_suspend); - wac_i2c->wac_pdata->late_resume_platform_hw(); - schedule_delayed_work(&wac_i2c->resume_work, HZ / 5); /* 200ms */ + printk(KERN_DEBUG "[E-PEN] %s.\n", __func__); + wacom_i2c_enable(wac_i2c); } #ifdef CONFIG_HAS_EARLYSUSPEND @@ -367,78 +597,118 @@ static ssize_t epen_firm_version_show(struct device *dev, printk(KERN_DEBUG "[E-PEN] %s: 0x%x|0x%X\n", __func__, wac_i2c->wac_feature->fw_version, Firmware_version_of_file); -#if defined(CONFIG_MACH_P4NOTE) return sprintf(buf, "%04X\t%04X\n", -#else - return sprintf(buf, "0x%X\t0x%X\n", -#endif wac_i2c->wac_feature->fw_version, Firmware_version_of_file); } +#if defined(WACOM_IMPORT_FW_ALGO) +static ssize_t epen_tuning_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + printk(KERN_DEBUG "[E-PEN] %s: %s\n", __func__, + tuning_version); + + return sprintf(buf, "%s\n", + tuning_version); +} +#endif + +static bool check_update_condition(struct wacom_i2c *wac_i2c, const char buf) +{ + u32 fw_ic_ver = wac_i2c->wac_feature->fw_version; + bool bUpdate = false; + + switch (buf) { + case 'F': + case 'I': + case 'B': + case 'K': + bUpdate = true; + break; + case 'R': + case 'W': + if (fw_ic_ver < + Firmware_version_of_file) + bUpdate = true; +#ifdef CONFIG_MACH_Q1_BD + /* Q1 board rev 0.3 */ + if (system_rev < 6) + if (fw_ic_ver != + Firmware_version_of_file) + bUpdate = true; +#endif + break; + default: + printk(KERN_ERR "[E-PEN] wrong parameter\n"); + bUpdate = false; + break; + } + + return bUpdate; +} + static ssize_t epen_firmware_update_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct wacom_i2c *wac_i2c = dev_get_drvdata(dev); - u8 *data; - u8 buf_if; int ret = 1; + u32 fw_ic_ver = wac_i2c->wac_feature->fw_version; + bool need_update = false; - disable_irq(wac_i2c->irq); -#ifdef WACOM_PDCT_WORK_AROUND - disable_irq(wac_i2c->irq_pdct); -#endif + printk(KERN_DEBUG "[E-PEN] %s\n", __func__); - buf_if = COM_QUERY; - data = wac_i2c->wac_feature->data; - wac_i2c->wac_feature->firm_update_status = 1; + need_update = check_update_condition(wac_i2c, *buf); + if (need_update == false) { + printk(KERN_DEBUG"[E-PEN] Pass Update." + "Cmd %c, IC ver %04x, Ker ver %04x\n", + *buf, fw_ic_ver, Firmware_version_of_file); + return count; + } - printk(KERN_DEBUG "[E-PEN] %s:\n", __func__); + /*start firm update*/ + mutex_lock(&wac_i2c->lock); + wacom_i2c_enable_irq(wac_i2c, false); + wac_i2c->wac_feature->firm_update_status = 1; - /* F and B are used by Factory app, and R is used when boot */ switch (*buf) { -#ifdef WACOM_UMS_UPDATE - /* Block UMS update for MR */ + /*ums*/ case 'F': - printk(KERN_ERR "[E-PEN] Start firmware flashing (UMS).\n"); - ret = wacom_i2c_load_fw(wac_i2c->client); + case 'U': + ret = wacom_i2c_fw_update_UMS(wac_i2c->client); break; -#endif + /*kernel*/ case 'B': + case 'K': printk(KERN_ERR - "[E-PEN] Start firmware flashing (kernel image).\n"); -#ifdef CONFIG_MACH_Q1_BD + "[E-PEN] Start firmware flashing (kernel image).\n"); +#if defined(CONFIG_MACH_Q1_BD) || defined(CONFIG_MACH_T0) ret = wacom_i2c_firm_update(wac_i2c); #else ret = wacom_i2c_flash(wac_i2c); #endif break; -#ifdef CONFIG_MACH_Q1_BD + /*booting*/ +#if defined(CONFIG_MACH_Q1_BD) \ + || defined(CONFIG_MACH_T0) case 'R': - /* Q1 board rev 0.3 */ - if (system_rev >= 6) { - if (wac_i2c->wac_feature->fw_version < - Firmware_version_of_file) - ret = wacom_i2c_firm_update(wac_i2c); + ret = wacom_i2c_firm_update(wac_i2c); + break; +#elif defined(CONFIG_MACH_P4NOTE) + case 'R': + if (fw_ic_ver == 0x0 + || fw_ic_ver < Firmware_version_of_file) { + printk(KERN_INFO "[E-PEN] Enter firmware update by sysfs.\n"); + update_fw_p4(wac_i2c); } else { - if (wac_i2c->wac_feature->fw_version != - Firmware_version_of_file) - ret = wacom_i2c_firm_update(wac_i2c); - } - if (ret > 0) { - enable_irq(wac_i2c->irq); -#ifdef WACOM_PDCT_WORK_AROUND - enable_irq(wac_i2c->irq_pdct); -#endif - return count; + printk(KERN_INFO "[E-PEN] Skip the firmware update by Condition.\n"); } break; #endif default: - printk(KERN_ERR "[E-PEN] wrong parameter.\n"); - goto param_err; + /*There's no default case*/ break; } @@ -449,14 +719,11 @@ static ssize_t epen_firmware_update_store(struct device *dev, printk(KERN_ERR "[E-PEN] Finish firmware flashing.\n"); - msleep(800); wacom_i2c_query(wac_i2c); - wac_i2c->wac_feature->firm_update_status = 2; - enable_irq(wac_i2c->irq); -#ifdef WACOM_PDCT_WORK_AROUND - enable_irq(wac_i2c->irq_pdct); -#endif + wac_i2c->wac_feature->firm_update_status = 2; + wacom_i2c_enable_irq(wac_i2c, true); + mutex_unlock(&wac_i2c->lock); return count; @@ -464,10 +731,8 @@ static ssize_t epen_firmware_update_store(struct device *dev, failure: wac_i2c->wac_feature->firm_update_status = -1; - enable_irq(wac_i2c->irq); -#ifdef WACOM_PDCT_WORK_AROUND - enable_irq(wac_i2c->irq_pdct); -#endif + wacom_i2c_enable_irq(wac_i2c, true); + mutex_unlock(&wac_i2c->lock); return -1; } @@ -482,6 +747,9 @@ static ssize_t epen_sampling_rate_store(struct device *dev, if (sscanf(buf, "%d", &value) == 1) { switch (value) { + case 0: + mode = COM_SAMPLERATE_STOP; + break; case 40: mode = COM_SAMPLERATE_40; break; @@ -497,16 +765,16 @@ static ssize_t epen_sampling_rate_store(struct device *dev, goto fail; } - disable_irq(wac_i2c->irq); - if (1 == i2c_master_send(wac_i2c->client, &mode, 1)) { + wacom_i2c_enable_irq(wac_i2c, false); + if (1 == wacom_i2c_send(wac_i2c, &mode, 1, false)) { printk(KERN_DEBUG "[E-PEN] sampling rate %d\n", value); msleep(100); } else { pr_err("[E-PEN] I2C write error\n"); - enable_irq(wac_i2c->irq); + wacom_i2c_enable_irq(wac_i2c, true); count = -1; } - enable_irq(wac_i2c->irq); + wacom_i2c_enable_irq(wac_i2c, true); } else { pr_err("[E-PEN] can't get sampling rate data\n"); @@ -583,10 +851,7 @@ static ssize_t epen_reset_store(struct device *dev, sscanf(buf, "%d", &val); if (val == 1) { - disable_irq(wac_i2c->irq); -#ifdef WACOM_PDCT_WORK_AROUND - disable_irq(wac_i2c->irq_pdct); -#endif + wacom_i2c_enable_irq(wac_i2c, false); /* Reset IC */ wacom_i2c_reset_hw(wac_i2c->wac_pdata); @@ -594,10 +859,7 @@ static ssize_t epen_reset_store(struct device *dev, /* I2C Test */ ret = wacom_i2c_query(wac_i2c); - enable_irq(wac_i2c->irq); -#ifdef WACOM_PDCT_WORK_AROUND - enable_irq(wac_i2c->irq_pdct); -#endif + wacom_i2c_enable_irq(wac_i2c, true); if (ret < 0) epen_reset_result = false; @@ -623,84 +885,94 @@ static ssize_t epen_reset_result_show(struct device *dev, } } +#ifdef WACOM_USE_BOXFILTER +static ssize_t epen_box_store(struct device *dev, +struct device_attribute *attr, + const char *buf, size_t count) +{ + struct wacom_i2c *wac_i2c = dev_get_drvdata(dev); + bool check_version = false; + int v1, v2, v3, v4; + int height; + + sscanf(buf, "%d%d%d%d%d", &height, &v1, &v2, &v3, &v4); + + if (height < 0 || height > 2) { + printk(KERN_DEBUG"[E-PEN] Height err %d\n", height); + return count; + } + + g_boxThreshold_C[height] = v1; + g_boxThreshold_X[height] = v2; + g_boxThreshold_Y[height] = v3; + g_boxThreshold_Trs[height] = v4; + + printk(KERN_DEBUG "[E-PEN] %s, v1 %d v2 %d v3 %d v4 %d\n", __func__, + v1, v2, v3, v4); + + return count; +} + +static ssize_t epen_box_result_show(struct device *dev, +struct device_attribute *attr, + char *buf) +{ + struct wacom_i2c *wac_i2c = dev_get_drvdata(dev); + + printk(KERN_DEBUG "[E-PEN] %s\n%d %d %d %d\n" + "%d %d %d %d\n%d %d %d %d\n", + __func__, + g_boxThreshold_C[0], g_boxThreshold_X[0], + g_boxThreshold_Y[0], g_boxThreshold_Trs[0], + g_boxThreshold_C[1], g_boxThreshold_X[1], + g_boxThreshold_Y[1], g_boxThreshold_Trs[1], + g_boxThreshold_C[2], g_boxThreshold_X[2], + g_boxThreshold_Y[2], g_boxThreshold_Trs[2]); + return sprintf(buf, "%d %d %d %d\n%d %d %d %d\n%d %d %d %d\n", + g_boxThreshold_C[0], g_boxThreshold_X[0], + g_boxThreshold_Y[0], g_boxThreshold_Trs[0], + g_boxThreshold_C[1], g_boxThreshold_X[1], + g_boxThreshold_Y[1], g_boxThreshold_Trs[1], + g_boxThreshold_C[2], g_boxThreshold_X[2], + g_boxThreshold_Y[2], g_boxThreshold_Trs[2]); +} +#endif + static ssize_t epen_checksum_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct wacom_i2c *wac_i2c = dev_get_drvdata(dev); bool check_version = false; - int ret; int val; - int i; - int retry = 3; - unsigned char data[6] = { 0, }; sscanf(buf, "%d", &val); #if defined(CONFIG_MACH_P4NOTE) - check_version = true; -#else + if (wac_i2c->checksum_result) + return count; + else + check_version = true; +#elif defined(CONFIG_MACH_Q1_BD) if (wac_i2c->wac_feature->fw_version >= 0x31E) check_version = true; +#elif defined(CONFIG_MACH_T0) + if (wac_i2c->wac_feature->fw_version == 0x179) { + wac_i2c->checksum_result = 1; + check_version = false; + } else + check_version = true; #endif if (val == 1 && check_version) { - disable_irq(wac_i2c->client->irq); -#ifdef WACOM_PDCT_WORK_AROUND - disable_irq(wac_i2c->irq_pdct); -#endif - - - data[0] = COM_CHECKSUM; - - while (retry--) { - ret = i2c_master_send(wac_i2c->client, &data[0], 1); - if (ret < 0) { - printk(KERN_DEBUG - "[E-PEN] i2c fail, retry, %d\n", - __LINE__); - continue; - } - - msleep(200); - ret = i2c_master_recv(wac_i2c->client, data, 5); - if (ret < 0) { - printk(KERN_DEBUG - "[E-PEN] i2c fail, retry, %d\n", - __LINE__); - continue; - } else if (data[0] == 0x1f) - break; - printk(KERN_DEBUG "[E-PEN] checksum retry\n"); - } + wacom_i2c_enable_irq(wac_i2c, false); - if (ret >= 0) { - printk(KERN_DEBUG - "[E-PEN] received checksum %x, %x, %x, %x, %x\n", - data[0], data[1], data[2], data[3], data[4]); - } - - for (i = 0; i < 5; ++i) { - if (data[i] != Firmware_checksum[i]) { - printk(KERN_DEBUG - "[E-PEN] checksum fail %dth %x %x\n", i, - data[i], Firmware_checksum[i]); - break; - } - } - if (i == 5) - epen_checksum_result = true; - else - epen_checksum_result = false; - - enable_irq(wac_i2c->client->irq); -#ifdef WACOM_PDCT_WORK_AROUND - enable_irq(wac_i2c->irq_pdct); -#endif + wacom_checksum(wac_i2c); - printk(KERN_DEBUG "[E-PEN] %s, result %d\n", __func__, - epen_checksum_result); + wacom_i2c_enable_irq(wac_i2c, true); } + printk(KERN_DEBUG "[E-PEN] %s, check %d, result %d\n", + __func__, check_version, wac_i2c->checksum_result); return count; } @@ -709,7 +981,9 @@ static ssize_t epen_checksum_result_show(struct device *dev, struct device_attribute *attr, char *buf) { - if (epen_checksum_result) { + struct wacom_i2c *wac_i2c = dev_get_drvdata(dev); + + if (wac_i2c->checksum_result) { printk(KERN_DEBUG "[E-PEN] checksum, PASS\n"); return sprintf(buf, "PASS\n"); } else { @@ -718,6 +992,67 @@ static ssize_t epen_checksum_result_show(struct device *dev, } } +#ifdef WACOM_CONNECTION_CHECK +static ssize_t epen_connection_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct wacom_i2c *wac_i2c = dev_get_drvdata(dev); + + printk(KERN_DEBUG + "[E-PEN] connection_check : %d\n", + wac_i2c->connection_check); + return sprintf(buf, "%s\n", + wac_i2c->connection_check ? + "OK" : "NG"); +} +#endif + +#if defined(CONFIG_MACH_P4NOTE) +static ssize_t epen_type_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct wacom_i2c *wac_i2c = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", wac_i2c->pen_type); +} + +static ssize_t epen_type_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct wacom_i2c *wac_i2c = dev_get_drvdata(dev); + int val; + + sscanf(buf, "%d", &val); + + wac_i2c->pen_type = !!val; + + return count; +} +#endif + +#ifdef BATTERY_SAVING_MODE +static ssize_t epen_saving_mode_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct wacom_i2c *wac_i2c = dev_get_drvdata(dev); + int val; + + if (sscanf(buf, "%u", &val) == 1) + wac_i2c->battery_saving_mode = !!val; + + if (wac_i2c->battery_saving_mode) { + if (wac_i2c->pen_insert) + wacom_i2c_disable(wac_i2c); + } else + wacom_i2c_enable(wac_i2c); + return count; +} +#endif + /* firmware update */ static DEVICE_ATTR(epen_firm_update, S_IWUSR | S_IWGRP, NULL, epen_firmware_update_store); @@ -726,10 +1061,17 @@ static DEVICE_ATTR(epen_firm_update_status, S_IRUGO, epen_firm_update_status_show, NULL); /* return firmware version */ static DEVICE_ATTR(epen_firm_version, S_IRUGO, epen_firm_version_show, NULL); +#if defined(WACOM_IMPORT_FW_ALGO) +/* return tuning data version */ +static DEVICE_ATTR(epen_tuning_version, S_IRUGO, + epen_tuning_version_show, NULL); +#endif #if defined(CONFIG_MACH_P4NOTE) static DEVICE_ATTR(epen_sampling_rate, S_IWUSR | S_IWGRP, NULL, epen_sampling_rate_store); +static DEVICE_ATTR(epen_type, + S_IRUGO | S_IWUSR | S_IWGRP, epen_type_show, epen_type_store); #else /* screen rotation */ static DEVICE_ATTR(epen_rotation, S_IWUSR | S_IWGRP, NULL, epen_rotation_store); @@ -746,12 +1088,32 @@ static DEVICE_ATTR(epen_checksum, S_IWUSR | S_IWGRP, NULL, epen_checksum_store); static DEVICE_ATTR(epen_checksum_result, S_IRUSR | S_IRGRP, epen_checksum_result_show, NULL); +#ifdef WACOM_USE_BOXFILTER +static DEVICE_ATTR(epen_box, S_IWUSR | S_IWGRP, NULL, epen_box_store); +static DEVICE_ATTR(epen_box_result, S_IRUSR | S_IRGRP, + epen_box_result_show, NULL); +#endif + +#ifdef WACOM_CONNECTION_CHECK +static DEVICE_ATTR(epen_connection, + S_IRUGO, epen_connection_show, NULL); +#endif + +#ifdef BATTERY_SAVING_MODE +static DEVICE_ATTR(epen_saving_mode, + S_IWUSR | S_IWGRP, NULL, epen_saving_mode_store); +#endif + static struct attribute *epen_attributes[] = { &dev_attr_epen_firm_update.attr, &dev_attr_epen_firm_update_status.attr, &dev_attr_epen_firm_version.attr, +#if defined(WACOM_IMPORT_FW_ALGO) + &dev_attr_epen_tuning_version.attr, +#endif #if defined(CONFIG_MACH_P4NOTE) &dev_attr_epen_sampling_rate.attr, + &dev_attr_epen_type.attr, #else &dev_attr_epen_rotation.attr, &dev_attr_epen_hand.attr, @@ -760,6 +1122,16 @@ static struct attribute *epen_attributes[] = { &dev_attr_epen_reset_result.attr, &dev_attr_epen_checksum.attr, &dev_attr_epen_checksum_result.attr, +#ifdef WACOM_USE_BOXFILTER + &dev_attr_epen_box.attr, + &dev_attr_epen_box_result.attr, +#endif +#ifdef WACOM_CONNECTION_CHECK + &dev_attr_epen_connection.attr, +#endif +#ifdef BATTERY_SAVING_MODE + &dev_attr_epen_saving_mode.attr, +#endif NULL, }; @@ -774,6 +1146,9 @@ static int wacom_i2c_probe(struct i2c_client *client, struct wacom_i2c *wac_i2c; struct input_dev *input; int ret = 0; +#if defined(CONFIG_MACH_T0) + int digitizer_type = 0; +#endif if (pdata == NULL) { printk(KERN_ERR "%s: no pdata\n", __func__); @@ -796,6 +1171,13 @@ static int wacom_i2c_probe(struct i2c_client *client, goto err_freemem; } + wac_i2c->client_boot = i2c_new_dummy(client->adapter, + WACOM_I2C_BOOT); + if (!wac_i2c->client_boot) { + dev_err(&client->dev, "Fail to register sub client[0x%x]\n", + WACOM_I2C_BOOT); + } + input = input_allocate_device(); if (NULL == input) { printk(KERN_ERR "[E-PEN] failed to allocate input device.\n"); @@ -813,6 +1195,10 @@ static int wacom_i2c_probe(struct i2c_client *client, wac_i2c->irq_pdct = gpio_to_irq(pdata->gpio_pendct); #endif +#ifdef WACOM_PEN_DETECT + wac_i2c->gpio_pen_insert = pdata->gpio_pen_insert; +#endif + /*Change below if irq is needed */ wac_i2c->irq_flag = 1; @@ -823,6 +1209,10 @@ static int wacom_i2c_probe(struct i2c_client *client, /* Firmware Feature */ wacom_i2c_init_firm_data(); +#ifdef WACOM_IMPORT_FW_ALGO + wac_i2c->use_offset_table = true; + wac_i2c->use_box_filter = false; +#endif #if defined(CONFIG_MACH_Q1_BD) /* Change Origin offset by rev */ @@ -830,10 +1220,49 @@ static int wacom_i2c_probe(struct i2c_client *client, origin_offset[0] = origin_offset_48[0]; origin_offset[1] = origin_offset_48[1]; } - /* Reset IC */ wacom_i2c_reset_hw(wac_i2c->wac_pdata); +#elif defined(CONFIG_MACH_T0) + wac_i2c->wac_pdata->late_resume_platform_hw(); + msleep(200); + + /*Set data by digitizer type*/ + digitizer_type = wacom_i2c_get_digitizer_type(); + + if (digitizer_type == EPEN_DTYPE_B746) { + printk(KERN_DEBUG"[E-PEN] Use Box filter\n"); + wac_i2c->use_box_filter = true; + } else if (digitizer_type == EPEN_DTYPE_B713) { + printk(KERN_DEBUG"[E-PEN] Reset tilt for B713\n"); + + /*Change tuning version for B713*/ + tuning_version = tuning_version_B713; + + memcpy(tilt_offsetX, tilt_offsetX_B713, sizeof(tilt_offsetX)); + memcpy(tilt_offsetY, tilt_offsetY_B713, sizeof(tilt_offsetY)); + } else if (digitizer_type == EPEN_DTYPE_B660) { + printk(KERN_DEBUG"[E-PEN] Reset tilt and origin for B660\n"); + + origin_offset[0] = EPEN_B660_ORG_X; + origin_offset[1] = EPEN_B660_ORG_Y; + memset(tilt_offsetX, 0, sizeof(tilt_offsetX)); + memset(tilt_offsetY, 0, sizeof(tilt_offsetY)); + wac_i2c->use_offset_table = false; + } + + /*Set switch type*/ + wac_i2c->invert_pen_insert = wacom_i2c_invert_by_switch_type(); +#ifdef WACOM_PDCT_WORK_AROUND + wac_i2c->pen_pdct = PDCT_NOSIGNAL; #endif +#endif + +#if defined(CONFIG_MACH_P4NOTE) + wac_i2c->wac_pdata->resume_platform_hw(); + msleep(200); +#endif + wac_i2c->power_enable = true; + ret = wacom_i2c_query(wac_i2c); if (ret < 0) @@ -841,22 +1270,13 @@ static int wacom_i2c_probe(struct i2c_client *client, else epen_reset_result = true; - INIT_WORK(&wac_i2c->update_work, update_work_func); - #if defined(CONFIG_MACH_P4NOTE) - if (pdata->xy_switch) { - input_set_abs_params(input, ABS_X, WACOM_POSY_OFFSET, - wac_i2c->wac_feature->y_max, 4, 0); - input_set_abs_params(input, ABS_Y, WACOM_POSX_OFFSET, - wac_i2c->wac_feature->x_max, 4, 0); - } else { - input_set_abs_params(input, ABS_X, WACOM_POSX_OFFSET, - wac_i2c->wac_feature->x_max, 4, 0); - input_set_abs_params(input, ABS_Y, WACOM_POSY_OFFSET, - wac_i2c->wac_feature->y_max, 4, 0); - } + input_set_abs_params(input, ABS_X, WACOM_POSX_OFFSET, + wac_i2c->wac_feature->x_max, 4, 0); + input_set_abs_params(input, ABS_Y, WACOM_POSY_OFFSET, + wac_i2c->wac_feature->y_max, 4, 0); input_set_abs_params(input, ABS_PRESSURE, 0, - wac_i2c->wac_feature->pressure_max, 0, 0); + WACOM_MAX_PRESSURE, 0, 0); #else input_set_abs_params(wac_i2c->input_dev, ABS_X, pdata->min_x, pdata->max_x, 4, 0); @@ -879,6 +1299,7 @@ static int wacom_i2c_probe(struct i2c_client *client, /*Set client data */ i2c_set_clientdata(client, wac_i2c); + i2c_set_clientdata(wac_i2c->client_boot, wac_i2c); /*Initializing for semaphor */ mutex_init(&wac_i2c->lock); @@ -888,34 +1309,6 @@ static int wacom_i2c_probe(struct i2c_client *client, INIT_DELAYED_WORK(&wac_i2c->pendct_dwork, wacom_i2c_pendct_work); #endif - /*Request IRQ */ - if (wac_i2c->irq_flag) { - ret = - request_threaded_irq(wac_i2c->irq, NULL, wacom_interrupt, - IRQF_DISABLED | IRQF_TRIGGER_RISING | - IRQF_ONESHOT, wac_i2c->name, wac_i2c); - if (ret < 0) { - printk(KERN_ERR - "[E-PEN]: failed to request irq(%d) - %d\n", - wac_i2c->irq, ret); - goto err_request_irq; - } - -#if defined(WACOM_PDCT_WORK_AROUND) - ret = - request_threaded_irq(wac_i2c->irq_pdct, NULL, - wacom_interrupt_pdct, - IRQF_DISABLED | IRQF_TRIGGER_RISING | - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - wac_i2c->name, wac_i2c); - if (ret < 0) { - printk(KERN_ERR - "[E-PEN]: failed to request irq(%d) - %d\n", - wac_i2c->irq_pdct, ret); - goto err_request_irq; - } -#endif - } #ifdef CONFIG_HAS_EARLYSUSPEND wac_i2c->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; wac_i2c->early_suspend.suspend = wacom_i2c_early_suspend; @@ -924,9 +1317,10 @@ static int wacom_i2c_probe(struct i2c_client *client, #endif wac_i2c->dev = device_create(sec_class, NULL, 0, NULL, "sec_epen"); - if (IS_ERR(wac_i2c->dev)) + if (IS_ERR(wac_i2c->dev)) { printk(KERN_ERR "Failed to create device(wac_i2c->dev)!\n"); - else { + goto err_sysfs_create_group; + } else { dev_set_drvdata(wac_i2c->dev, wac_i2c); ret = sysfs_create_group(&wac_i2c->dev->kobj, &epen_attr_group); if (ret) { @@ -935,18 +1329,15 @@ static int wacom_i2c_probe(struct i2c_client *client, goto err_sysfs_create_group; } } -#if defined(CONFIG_MACH_P4NOTE) - if (Firmware_version_of_file > wac_i2c->wac_feature->fw_version) - schedule_work(&wac_i2c->update_work); -#elif defined(CONFIG_MACH_Q1_BD) + /* firmware info */ printk(KERN_NOTICE "[E-PEN] wacom fw ver : 0x%x, new fw ver : 0x%x\n", wac_i2c->wac_feature->fw_version, Firmware_version_of_file); -#endif #ifdef CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK INIT_DELAYED_WORK(&wac_i2c->dvfs_work, free_dvfs_lock); - if (exynos_cpufreq_get_level(500000, &wac_i2c->cpufreq_level)) + if (exynos_cpufreq_get_level(WACOM_DVFS_LOCK_FREQ, + &wac_i2c->cpufreq_level)) printk(KERN_ERR "[E-PEN] exynos_cpufreq_get_level Error\n"); #ifdef SEC_BUS_LOCK wac_i2c->dvfs_lock_status = false; @@ -956,17 +1347,41 @@ static int wacom_i2c_probe(struct i2c_client *client, #endif /* SEC_BUS_LOCK */ #endif /* CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK */ - return 0; + /*Request IRQ */ + if (wac_i2c->irq_flag) { + ret = + request_threaded_irq(wac_i2c->irq, NULL, wacom_interrupt, + IRQF_DISABLED | IRQF_TRIGGER_RISING | + IRQF_ONESHOT, wac_i2c->name, wac_i2c); + if (ret < 0) { + printk(KERN_ERR + "[E-PEN] failed to request irq(%d) - %d\n", + wac_i2c->irq, ret); + goto err_request_irq; + } - err_sysfs_create_group: - free_irq(wac_i2c->irq, wac_i2c); -#ifdef WACOM_PDCT_WORK_AROUND - free_irq(wac_i2c->irq_pdct, wac_i2c); +#if defined(WACOM_PDCT_WORK_AROUND) + ret = + request_threaded_irq(wac_i2c->irq_pdct, NULL, + wacom_interrupt_pdct, + IRQF_DISABLED | IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + wac_i2c->name, wac_i2c); + if (ret < 0) { + printk(KERN_ERR + "[E-PEN] failed to request irq(%d) - %d\n", + wac_i2c->irq_pdct, ret); + goto err_request_irq; + } #endif + } + + return 0; + err_request_irq: + err_sysfs_create_group: err_register_device: input_unregister_device(input); - input = NULL; err_input_allocate_device: input_free_device(input); err_freemem: |