| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206 |
- /* drivers/input/touchscreen/gt1x_tpd.c
- *
- * 2010 - 2014 Goodix Technology.
- *
- * 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 a reference
- * to you, when you are integrating the GOODiX's CTP IC into your system,
- * 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.
- *
- * Version: 1.0
- * Revision Record:
- * V1.0: first release. 2014/09/28.
- *
- */
- #include "include/gt1x_tpd_common.h"
- #if TPD_SUPPORT_I2C_DMA
- #include <linux/dma-mapping.h>
- #endif
- #ifdef CONFIG_GTP_ICS_SLOT_REPORT
- #include <linux/input/mt.h>
- #endif
- #include <linux/regulator/consumer.h>
- #include <linux/of.h>
- #include <linux/of_irq.h>
- /*1 enable,0 disable,touch_panel_eint default status, need to confirm after register eint*/
- int irq_flag = 1;
- static spinlock_t irq_flag_lock;
- /*0 power off,default, 1 power on*/
- static int power_flag;
- static int tpd_flag;
- int tpd_halt = 0;
- static int tpd_eint_mode = 1;
- static struct task_struct *thread;
- static int tpd_tui_flag;
- static int tpd_tui_low_power_skipped;
- DEFINE_MUTEX(tui_lock);
- static struct task_struct *probe_thread;
- static int tpd_polling_time = 50;
- static DECLARE_WAIT_QUEUE_HEAD(waiter);
- static bool gtp_suspend;
- DECLARE_WAIT_QUEUE_HEAD(init_waiter);
- DEFINE_MUTEX(i2c_access);
- unsigned int touch_irq = 0;
- u8 int_type = 0;
- #if (defined(TPD_WARP_START) && defined(TPD_WARP_END))
- static int tpd_wb_start_local[TPD_WARP_CNT] = TPD_WARP_START;
- static int tpd_wb_end_local[TPD_WARP_CNT] = TPD_WARP_END;
- #endif
- #if (defined(TPD_HAVE_CALIBRATION) && !defined(TPD_CUSTOM_CALIBRATION))
- static int tpd_def_calmat_local[8] = TPD_CALIBRATION_MATRIX;
- #endif
- static int tpd_event_handler(void *unused);
- static int tpd_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id);
- static int tpd_i2c_detect(struct i2c_client *client, struct i2c_board_info *info);
- static int tpd_i2c_remove(struct i2c_client *client);
- static irqreturn_t tpd_eint_interrupt_handler(unsigned irq, struct irq_desc *desc);
- #define GTP_DRIVER_NAME "gt1x"
- static const struct i2c_device_id tpd_i2c_id[] = { {GTP_DRIVER_NAME, 0}, {} };
- static unsigned short force[] = { 0, GTP_I2C_ADDRESS, I2C_CLIENT_END, I2C_CLIENT_END };
- static const unsigned short *const forces[] = { force, NULL };
- static const struct of_device_id tpd_of_match[] = {
- {.compatible = "mediatek,cap_touch"},
- {},
- };
- static struct i2c_driver tpd_i2c_driver = {
- .probe = tpd_i2c_probe,
- .remove = tpd_i2c_remove,
- .detect = tpd_i2c_detect,
- .driver.name = GTP_DRIVER_NAME,
- .driver = {
- .name = GTP_DRIVER_NAME,
- .of_match_table = tpd_of_match,
- },
- .id_table = tpd_i2c_id,
- .address_list = (const unsigned short *)forces,
- };
- #if TPD_SUPPORT_I2C_DMA
- static u8 *gpDMABuf_va;
- static dma_addr_t gpDMABuf_pa;
- struct mutex dma_mutex;
- DEFINE_MUTEX(dma_mutex);
- static s32 i2c_dma_write_mtk(u16 addr, u8 *buffer, s32 len)
- {
- s32 ret = 0;
- s32 pos = 0;
- s32 transfer_length;
- u16 address = addr;
- struct i2c_msg msg = {
- .flags = !I2C_M_RD,
- .ext_flag = (gt1x_i2c_client->ext_flag | I2C_ENEXT_FLAG | I2C_DMA_FLAG),
- .addr = (gt1x_i2c_client->addr & I2C_MASK_FLAG),
- .timing = I2C_MASTER_CLOCK,
- .buf = (u8 *)(uintptr_t)gpDMABuf_pa,
- };
- mutex_lock(&dma_mutex);
- while (pos != len) {
- if (len - pos > (IIC_DMA_MAX_TRANSFER_SIZE - GTP_ADDR_LENGTH))
- transfer_length = IIC_DMA_MAX_TRANSFER_SIZE - GTP_ADDR_LENGTH;
- else
- transfer_length = len - pos;
- gpDMABuf_va[0] = (address >> 8) & 0xFF;
- gpDMABuf_va[1] = address & 0xFF;
- memcpy(&gpDMABuf_va[GTP_ADDR_LENGTH], &buffer[pos], transfer_length);
- msg.len = transfer_length + GTP_ADDR_LENGTH;
- if (!gtp_suspend) {/*workround log too much*/
- ret = i2c_transfer(gt1x_i2c_client->adapter, &msg, 1);
- if (ret != 1) {
- GTP_INFO("I2c Transfer error! (%d)", ret);
- ret = ERROR_IIC;
- break;
- }
- } else {
- ret = ERROR_IIC;
- break;
- }
- ret = 0;
- pos += transfer_length;
- address += transfer_length;
- }
- mutex_unlock(&dma_mutex);
- return ret;
- }
- static s32 i2c_dma_read_mtk(u16 addr, u8 *buffer, s32 len)
- {
- s32 ret = ERROR;
- s32 pos = 0;
- s32 transfer_length;
- u16 address = addr;
- u8 addr_buf[GTP_ADDR_LENGTH] = { 0 };
- struct i2c_msg msgs[2] = {
- {
- .flags = 0, /*!I2C_M_RD,*/
- .addr = (gt1x_i2c_client->addr & I2C_MASK_FLAG),
- .timing = I2C_MASTER_CLOCK,
- .len = GTP_ADDR_LENGTH,
- .buf = addr_buf,
- },
- {
- .flags = I2C_M_RD,
- .ext_flag = (gt1x_i2c_client->ext_flag | I2C_ENEXT_FLAG | I2C_DMA_FLAG),
- .addr = (gt1x_i2c_client->addr & I2C_MASK_FLAG),
- .timing = I2C_MASTER_CLOCK,
- .buf = (u8 *)(uintptr_t)gpDMABuf_pa,
- },
- };
- mutex_lock(&dma_mutex);
- while (pos != len) {
- if (len - pos > IIC_DMA_MAX_TRANSFER_SIZE)
- transfer_length = IIC_DMA_MAX_TRANSFER_SIZE;
- else
- transfer_length = len - pos;
- msgs[0].buf[0] = (address >> 8) & 0xFF;
- msgs[0].buf[1] = address & 0xFF;
- msgs[1].len = transfer_length;
- ret = i2c_transfer(gt1x_i2c_client->adapter, msgs, 2);
- if (ret != 2) {
- GTP_ERROR("I2C Transfer error! (%d)", ret);
- ret = ERROR_IIC;
- break;
- }
- ret = 0;
- memcpy(&buffer[pos], gpDMABuf_va, transfer_length);
- pos += transfer_length;
- address += transfer_length;
- };
- mutex_unlock(&dma_mutex);
- return ret;
- }
- #else
- static s32 i2c_write_mtk(u16 addr, u8 *buffer, s32 len)
- {
- s32 ret;
- struct i2c_msg msg = {
- .flags = 0,
- #ifdef CONFIG_MTK_I2C_EXTENSION
- .addr = (gt1x_i2c_client->addr & I2C_MASK_FLAG) | (I2C_ENEXT_FLAG), /*remain*/
- .timing = I2C_MASTER_CLOCK,
- #else
- .addr = gt1x_i2c_client->addr, /*remain*/
- #endif
- };
- ret = _do_i2c_write(&msg, addr, buffer, len);
- return ret;
- }
- static s32 i2c_read_mtk(u16 addr, u8 *buffer, s32 len)
- {
- int ret;
- u8 addr_buf[GTP_ADDR_LENGTH] = { (addr >> 8) & 0xFF, addr & 0xFF };
- struct i2c_msg msgs[2] = {
- {
- #ifdef CONFIG_MTK_I2C_EXTENSION
- .addr = ((gt1x_i2c_client->addr & I2C_MASK_FLAG) | (I2C_ENEXT_FLAG)),
- .timing = I2C_MASTER_CLOCK,
- #else
- .addr = gt1x_i2c_client->addr,
- #endif
- .flags = 0,
- .buf = addr_buf,
- .len = GTP_ADDR_LENGTH,
- },
- {
- #ifdef CONFIG_MTK_I2C_EXTENSION
- .addr = ((gt1x_i2c_client->addr & I2C_MASK_FLAG) | (I2C_ENEXT_FLAG)),
- .timing = I2C_MASTER_CLOCK,
- #else
- .addr = gt1x_i2c_client->addr,
- #endif
- .flags = I2C_M_RD,
- },
- };
- ret = _do_i2c_read(msgs, addr, buffer, len);
- return ret;
- }
- #endif/* TPD_SUPPORT_I2C_DMA */
- /**
- * @return: return 0 if success, otherwise return a negative number
- * which contains the error code.
- */
- s32 gt1x_i2c_read(u16 addr, u8 *buffer, s32 len)
- {
- #if TPD_SUPPORT_I2C_DMA
- return i2c_dma_read_mtk(addr, buffer, len);
- #else
- return i2c_read_mtk(addr, buffer, len);
- #endif
- }
- /**
- * @return: return 0 if success, otherwise return a negative number
- * which contains the error code.
- */
- s32 gt1x_i2c_write(u16 addr, u8 *buffer, s32 len)
- {
- #if TPD_SUPPORT_I2C_DMA
- return i2c_dma_write_mtk(addr, buffer, len);
- #else
- return i2c_write_mtk(addr, buffer, len);
- #endif
- }
- #ifdef TPD_REFRESH_RATE
- /*******************************************************
- Function:
- Write refresh rate
- Input:
- rate: refresh rate N (Duration=5+N ms, N=0~15)
- Output:
- Executive outcomes.0---succeed.
- *******************************************************/
- static u8 gt1x_set_refresh_rate(u8 rate)
- {
- u8 buf[1] = { rate };
- if (rate > 0xf) {
- GTP_ERROR("Refresh rate is over range (%d)", rate);
- return ERROR_VALUE;
- }
- GTP_INFO("Refresh rate change to %d", rate);
- return gt1x_i2c_write(GTP_REG_REFRESH_RATE, buf, sizeof(buf));
- }
- /*******************************************************
- Function:
- Get refresh rate
- Output:
- Refresh rate or error code
- *******************************************************/
- static u8 gt1x_get_refresh_rate(void)
- {
- int ret;
- u8 buf[1] = { 0x00 };
- ret = gt1x_i2c_read(GTP_REG_REFRESH_RATE, buf, sizeof(buf));
- if (ret < 0)
- return ret;
- GTP_INFO("Refresh rate is %d", buf[0]);
- return buf[0];
- }
- /*=============================================================*/
- static ssize_t show_refresh_rate(struct device *dev, struct device_attribute *attr, char *buf)
- {
- int ret = gt1x_get_refresh_rate();
- if (ret < 0)
- return 0;
- else
- return sprintf(buf, "%d\n", ret);
- }
- static ssize_t store_refresh_rate(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
- {
- unsigned long rate;
- int ret;
- ret = kstrtoul(buf, 0, &rate);
- gt1x_set_refresh_rate(rate);
- return size;
- }
- static DEVICE_ATTR(tpd_refresh_rate, 0664, show_refresh_rate, store_refresh_rate);
- static struct device_attribute *gt9xx_attrs[] = {
- &dev_attr_tpd_refresh_rate,
- };
- #endif
- /*=============================================================*/
- static int tpd_i2c_detect(struct i2c_client *client, struct i2c_board_info *info)
- {
- strcpy(info->type, "mtk-tpd");
- return 0;
- }
- static int tpd_power_on(void)
- {
- gt1x_power_switch(SWITCH_ON);
- gt1x_select_addr();
- msleep(20);
- if (gt1x_get_chip_type() != 0)
- return -1;
- if (gt1x_reset_guitar() != 0)
- return -1;
- return 0;
- }
- void gt1x_irq_enable(void)
- {
- unsigned long flags;
- spin_lock_irqsave(&irq_flag_lock, flags);
- if (irq_flag == 0) {
- irq_flag = 1;
- spin_unlock_irqrestore(&irq_flag_lock, flags);
- enable_irq(touch_irq);
- } else if (irq_flag == 1) {
- spin_unlock_irqrestore(&irq_flag_lock, flags);
- GTP_INFO("Touch Eint already enabled!");
- } else {
- spin_unlock_irqrestore(&irq_flag_lock, flags);
- GTP_ERROR("Invalid irq_flag %d!", irq_flag);
- }
- /*GTP_INFO("Enable irq_flag=%d",irq_flag);*/
- }
- void gt1x_irq_disable(void)
- {
- unsigned long flags;
- spin_lock_irqsave(&irq_flag_lock, flags);
- if (irq_flag == 1) {
- irq_flag = 0;
- spin_unlock_irqrestore(&irq_flag_lock, flags);
- disable_irq(touch_irq);
- } else if (irq_flag == 0) {
- spin_unlock_irqrestore(&irq_flag_lock, flags);
- GTP_INFO("Touch Eint already disabled!");
- } else {
- spin_unlock_irqrestore(&irq_flag_lock, flags);
- GTP_ERROR("Invalid irq_flag %d!", irq_flag);
- }
- /*GTP_INFO("Disable irq_flag=%d",irq_flag);*/
- }
- void gt1x_power_switch(s32 state)
- {
- #if !defined(CONFIG_MTK_LEGACY) || defined(CONFIG_ARCH_MT6580)
- int ret = 0;
- #endif
- GTP_GPIO_OUTPUT(GTP_RST_PORT, 0);
- GTP_GPIO_OUTPUT(GTP_INT_PORT, 0);
- msleep(20);
- switch (state) {
- case SWITCH_ON:
- if (power_flag == 0) {
- GTP_DEBUG("Power switch on!");
- #if !defined(CONFIG_MTK_LEGACY)
- ret = regulator_enable(tpd->reg); /*enable regulator*/
- if (ret)
- GTP_ERROR("regulator_enable() failed!\n");
- #else
- #ifdef TPD_POWER_SOURCE_CUSTOM
- #ifdef CONFIG_ARCH_MT6580
- ret = regulator_set_voltage(tpd->reg, 2800000, 2800000); /*set 2.8v*/
- if (ret)
- GTP_DEBUG("regulator_set_voltage() failed!\n");
- ret = regulator_enable(tpd->reg); /*enable regulator*/
- if (ret)
- GTP_DEBUG("regulator_enable() failed!\n");
- #else
- hwPowerOn(TPD_POWER_SOURCE_CUSTOM, VOL_2800, "TP");
- #endif
- #endif
- #endif
- power_flag = 1;
- } else {
- /*GTP_DEBUG("Power already is on!");*/
- }
- break;
- case SWITCH_OFF:
- if (power_flag == 1) {
- GTP_DEBUG("Power switch off!");
- #if !defined(CONFIG_MTK_LEGACY)
- ret = regulator_disable(tpd->reg); /*disable regulator*/
- if (ret)
- GTP_ERROR("regulator_disable() failed!\n");
- #else
- #ifdef TPD_POWER_SOURCE_CUSTOM
- #ifdef CONFIG_ARCH_MT6580
- ret = regulator_disable(tpd->reg); /*disable regulator*/
- if (ret)
- GTP_DEBUG("regulator_disable() failed!\n");
- #else
- hwPowerDown(TPD_POWER_SOURCE_CUSTOM, "TP");
- #endif
- #endif
- #endif
- power_flag = 0;
- } else {
- /*GTP_DEBUG("Power already is off!");*/
- }
- break;
- default:
- GTP_ERROR("Invalid power switch command!");
- break;
- }
- }
- int gt1x_is_tpd_halt(void)
- {
- return tpd_halt;
- }
- static int tpd_irq_registration(void)
- {
- struct device_node *node = NULL;
- int ret = 0;
- u32 ints[2] = { 0, 0 };
- GTP_INFO("Device Tree Tpd_irq_registration!");
- node = of_find_matching_node(node, touch_of_match);
- if (node) {
- of_property_read_u32_array(node, "debounce", ints, ARRAY_SIZE(ints));
- gpio_set_debounce(ints[0], ints[1]);
- touch_irq = irq_of_parse_and_map(node, 0);
- GTP_INFO("Device gt1x_int_type = %d!", gt1x_int_type);
- if (!gt1x_int_type) {/*EINTF_TRIGGER*/
- ret =
- request_irq(touch_irq, (irq_handler_t) tpd_eint_interrupt_handler, IRQF_TRIGGER_RISING,
- "TOUCH_PANEL-eint", NULL);
- if (ret > 0) {
- ret = -1;
- GTP_ERROR("tpd request_irq IRQ LINE NOT AVAILABLE!.");
- }
- } else {
- ret =
- request_irq(touch_irq, (irq_handler_t) tpd_eint_interrupt_handler, IRQF_TRIGGER_FALLING,
- "TOUCH_PANEL-eint", NULL);
- if (ret > 0) {
- ret = -1;
- GTP_ERROR("tpd request_irq IRQ LINE NOT AVAILABLE!.");
- }
- }
- } else {
- GTP_ERROR("tpd request_irq can not find touch eint device node!.");
- ret = -1;
- }
- GTP_INFO("[%s]irq:%d, debounce:%d-%d:", __func__, touch_irq, ints[0], ints[1]);
- return ret;
- }
- int tpd_reregister_from_tui(void)
- {
- int ret = 0;
- free_irq(touch_irq, NULL);
- ret = tpd_irq_registration();
- if (ret < 0) {
- ret = -1;
- GTP_ERROR("tpd request_irq IRQ LINE NOT AVAILABLE!.");
- }
- return ret;
- }
- static int tpd_registration(void *client)
- {
- s32 err = 0;
- s32 idx = 0;
- gt1x_i2c_client = client;
- if (gt1x_init()) {
- /* TP resolution == LCD resolution, no need to match resolution when initialized fail */
- gt1x_abs_x_max = 0;
- gt1x_abs_y_max = 0;
- }
- thread = kthread_run(tpd_event_handler, 0, TPD_DEVICE);
- if (IS_ERR(thread)) {
- err = PTR_ERR(thread);
- GTP_INFO(TPD_DEVICE " failed to create kernel thread: %d\n", err);
- }
- if (tpd_dts_data.use_tpd_button) {
- for (idx = 0; idx < tpd_dts_data.tpd_key_num; idx++)
- input_set_capability(tpd->dev, EV_KEY, tpd_dts_data.tpd_key_local[idx]);
- }
- #ifdef CONFIG_GTP_GESTURE_WAKEUP
- input_set_capability(tpd->dev, EV_KEY, KEY_GESTURE);
- #endif
- GTP_GPIO_AS_INT(GTP_INT_PORT);
- msleep(50);
- /* EINT device tree, default EINT enable */
- tpd_irq_registration();
- #ifdef CONFIG_GTP_ESD_PROTECT
- /* must before auto update */
- gt1x_init_esd_protect();
- gt1x_esd_switch(SWITCH_ON);
- #endif
- #ifdef CONFIG_GTP_AUTO_UPDATE
- thread = kthread_run(gt1x_auto_update_proc, (void *)NULL, "gt1x_auto_update");
- if (IS_ERR(thread)) {
- err = PTR_ERR(thread);
- GTP_INFO(TPD_DEVICE " failed to create auto-update thread: %d\n", err);
- }
- #endif
- return 0;
- }
- static s32 tpd_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
- {
- int err = 0;
- /*int count = 0;*/
- GTP_INFO("tpd_i2c_probe start.");
- #ifdef CONFIG_MTK_BOOT
- if (RECOVERY_BOOT == get_boot_mode())
- return 0;
- #endif
- probe_thread = kthread_run(tpd_registration, (void *)client, "tpd_probe");
- if (IS_ERR(probe_thread)) {
- err = PTR_ERR(probe_thread);
- GTP_INFO(TPD_DEVICE " failed to create probe thread: %d\n", err);
- return err;
- }
- GTP_INFO("tpd_i2c_probe start.wait_event_interruptible");
- wait_event_interruptible_timeout(init_waiter, check_flag == true, 5 * HZ);
- GTP_INFO("tpd_i2c_probe end.wait_event_interruptible");
- /*
- do {
- GTP_INFO("ZH tpd_i2c_probe A count = %d", count);
- msleep(20);
- GTP_INFO("ZH tpd_i2c_probe B count = %d", count);
- count++;
- if (check_flag == true)
- break;
- } while (count < 300);
- GTP_INFO("tpd_i2c_probe done.count = %d, flag = %d", count, tpd_load_status);
- */
- return 0;
- }
- static irqreturn_t tpd_eint_interrupt_handler(unsigned irq, struct irq_desc *desc)
- {
- unsigned long flags;
- TPD_DEBUG_PRINT_INT;
- tpd_flag = 1;
- spin_lock_irqsave(&irq_flag_lock, flags);
- if (irq_flag == 0) {
- spin_unlock_irqrestore(&irq_flag_lock, flags);
- return IRQ_HANDLED;
- }
- /* enter EINT handler disable INT, make sure INT is disable when handle touch event including top/bottom half */
- /* use _nosync to avoid deadlock */
- irq_flag = 0;
- spin_unlock_irqrestore(&irq_flag_lock, flags);
- disable_irq_nosync(touch_irq);
- /*GTP_INFO("disable irq_flag=%d",irq_flag);*/
- wake_up_interruptible(&waiter);
- return IRQ_HANDLED;
- }
- static int tpd_history_x, tpd_history_y;
- void gt1x_touch_down(s32 x, s32 y, s32 size, s32 id)
- {
- #ifdef CONFIG_GTP_CHANGE_X2Y
- GTP_SWAP(x, y);
- #endif
- #ifdef CONFIG_CUSTOM_LCM_X
- unsigned long lcm_x = 0, lcm_y = 0;
- int ret;
- #endif
- #ifdef CONFIG_GTP_ICS_SLOT_REPORT
- input_mt_slot(tpd->dev, id);
- input_report_abs(tpd->dev, ABS_MT_PRESSURE, size);
- input_report_abs(tpd->dev, ABS_MT_TOUCH_MAJOR, size);
- input_report_abs(tpd->dev, ABS_MT_TRACKING_ID, id);
- input_report_abs(tpd->dev, ABS_MT_POSITION_X, x);
- input_report_abs(tpd->dev, ABS_MT_POSITION_Y, y);
- #else
- input_report_key(tpd->dev, BTN_TOUCH, 1);
- if ((!size) && (!id)) {
- /* for virtual button */
- input_report_abs(tpd->dev, ABS_MT_PRESSURE, 100);
- input_report_abs(tpd->dev, ABS_MT_TOUCH_MAJOR, 100);
- } else {
- input_report_abs(tpd->dev, ABS_MT_PRESSURE, size);
- input_report_abs(tpd->dev, ABS_MT_TOUCH_MAJOR, size);
- input_report_abs(tpd->dev, ABS_MT_TRACKING_ID, id);
- }
- #ifdef CONFIG_CUSTOM_LCM_X
- ret = kstrtoul(CONFIG_CUSTOM_LCM_X, 0, &lcm_x);
- if (ret)
- GTP_ERROR("Touch down get lcm_x failed");
- ret = kstrtoul(CONFIG_CUSTOM_LCM_Y, 0, &lcm_y);
- if (ret)
- GTP_ERROR("Touch down get lcm_y failed");
- if (x < lcm_x)
- x = 0;
- else
- x = x - lcm_x;
- if (y < lcm_y)
- y = 0;
- else
- y = y - lcm_y;
- GTP_DEBUG("x:%d, y:%d, lcm_x:%lu, lcm_y:%lu", x, y, lcm_x, lcm_y);
- #endif
- input_report_abs(tpd->dev, ABS_MT_POSITION_X, x);
- input_report_abs(tpd->dev, ABS_MT_POSITION_Y, y);
- input_mt_sync(tpd->dev);
- #endif
- TPD_DEBUG_SET_TIME;
- TPD_EM_PRINT(x, y, x, y, id, 1);
- tpd_history_x = x;
- tpd_history_y = y;
- #ifdef CONFIG_MTK_BOOT
- if (tpd_dts_data.use_tpd_button) {
- if (FACTORY_BOOT == get_boot_mode() || RECOVERY_BOOT == get_boot_mode())
- tpd_button(x, y, 1);
- }
- #endif
- }
- void gt1x_touch_up(s32 id)
- {
- #ifdef CONFIG_GTP_ICS_SLOT_REPORT
- input_mt_slot(tpd->dev, id);
- input_report_abs(tpd->dev, ABS_MT_TRACKING_ID, -1);
- #else
- input_report_key(tpd->dev, BTN_TOUCH, 0);
- input_mt_sync(tpd->dev);
- #endif
- TPD_DEBUG_SET_TIME;
- TPD_EM_PRINT(tpd_history_x, tpd_history_y, tpd_history_x, tpd_history_y, id, 0);
- tpd_history_x = 0;
- tpd_history_y = 0;
- #ifdef CONFIG_MTK_BOOT
- if (tpd_dts_data.use_tpd_button) {
- if (FACTORY_BOOT == get_boot_mode() || RECOVERY_BOOT == get_boot_mode())
- tpd_button(0, 0, 0);
- }
- #endif
- }
- #ifdef CONFIG_GTP_CHARGER_SWITCH
- u32 gt1x_get_charger_status(void)
- {
- u32 chr_status = 0;
- #ifdef MT6573
- chr_status = *(volatile u32 *)CHR_CON0;
- chr_status &= (1 << 13);
- #else /* ( defined(MT6575) || defined(MT6577) || defined(MT6589) ) */
- chr_status = upmu_is_chr_det();
- #endif
- return chr_status;
- }
- #endif
- static int tpd_event_handler(void *unused)
- {
- u8 finger = 0;
- u8 end_cmd = 0;
- s32 ret = 0;
- u8 point_data[11] = { 0 };
- struct sched_param param = {.sched_priority = 4};
- sched_setscheduler(current, SCHED_RR, ¶m);
- do {
- set_current_state(TASK_INTERRUPTIBLE);
- if (tpd_eint_mode) {
- wait_event_interruptible(waiter, tpd_flag != 0);
- tpd_flag = 0;
- } else {
- GTP_DEBUG("Polling coordinate mode!");
- msleep(tpd_polling_time);
- }
- set_current_state(TASK_RUNNING);
- mutex_lock(&i2c_access);
- /* don't reset before "if (tpd_halt..." */
- #ifdef CONFIG_GTP_GESTURE_WAKEUP
- ret = gesture_event_handler(tpd->dev);
- if (ret >= 0) {
- gt1x_irq_enable();
- mutex_unlock(&i2c_access);
- continue;
- }
- #endif
- if (tpd_halt) {
- mutex_unlock(&i2c_access);
- GTP_DEBUG("return for interrupt after suspend... ");
- continue;
- }
- /* read coordinates */
- ret = gt1x_i2c_read(GTP_READ_COOR_ADDR, point_data, sizeof(point_data));
- if (ret < 0) {
- GTP_ERROR("I2C transfer error!");
- #ifndef CONFIG_GTP_ESD_PROTECT
- gt1x_power_reset();
- #endif
- goto exit_work_func;
- }
- finger = point_data[0];
- /* response to a ic request */
- if (finger == 0x00)
- gt1x_request_event_handler();
- if ((finger & 0x80) == 0) {
- #ifdef CONFIG_HOTKNOT_BLOCK_RW
- if (!hotknot_paired_flag) {
- #endif
- gt1x_irq_enable();
- mutex_unlock(&i2c_access);
- continue;
- }
- #ifdef CONFIG_HOTKNOT_BLOCK_RW
- }
- ret = hotknot_event_handler(point_data);
- if (!ret)
- goto exit_work_func;
- #endif
- #ifdef CONFIG_GTP_PROXIMITY
- ret = gt1x_prox_event_handler(point_data);
- if (ret > 0)
- goto exit_work_func;
- #endif
- #ifdef CONFIG_GTP_WITH_STYLUS
- ret = gt1x_touch_event_handler(point_data, tpd->dev, pen_dev);
- #else
- ret = gt1x_touch_event_handler(point_data, tpd->dev, NULL);
- #endif
- if (ret) {
- gt1x_irq_enable();
- mutex_unlock(&i2c_access);
- continue;
- }
- exit_work_func:
- if (!gt1x_rawdiff_mode) {
- ret = gt1x_i2c_write(GTP_READ_COOR_ADDR, &end_cmd, 1);
- if (ret < 0)
- GTP_INFO("I2C write end_cmd error!");
- }
- gt1x_irq_enable();
- mutex_unlock(&i2c_access);
- } while (!kthread_should_stop());
- return 0;
- }
- int gt1x_debug_proc(u8 *buf, int count)
- {
- char mode_str[50] = { 0 };
- int mode;
- int ret;
- ret = sscanf(buf, "%s %d", (char *)&mode_str, &mode);
- if (ret < 0) {
- GTP_ERROR("gt1x_debug_proc sscanf failed");
- return ret;
- }
- /***********POLLING/EINT MODE switch****************/
- if (strcmp(mode_str, "polling") == 0) {
- if (mode >= 10 && mode <= 200) {
- GTP_INFO("Switch to polling mode, polling time is %d", mode);
- tpd_eint_mode = 0;
- tpd_polling_time = mode;
- tpd_flag = 1;
- wake_up_interruptible(&waiter);
- } else {
- GTP_INFO("Wrong polling time, please set between 10~200ms");
- }
- return count;
- }
- if (strcmp(mode_str, "eint") == 0) {
- GTP_INFO("Switch to eint mode");
- tpd_eint_mode = 1;
- return count;
- }
- /**********************************************/
- if (strcmp(mode_str, "switch") == 0) {
- if (mode == 0) /*turn off*/
- tpd_off();
- else if (mode == 1) /*turn on*/
- tpd_on();
- else
- GTP_ERROR("error mode :%d", mode);
- return count;
- } else if (strcmp(mode_str, "enable_irq") == 0) {
- if (mode == 0) {
- GTP_ERROR("enable_irq 0, touch_irq = %d, irq_flag = %d",
- (int)touch_irq, irq_flag);
- disable_irq(touch_irq);
- } else if (mode == 1) {
- GTP_ERROR("enable_irq 1, touch_irq = %d, irq_flag = %d",
- (int)touch_irq, irq_flag);
- enable_irq(touch_irq);
- } else
- GTP_ERROR("error mode :%d", mode);
- } else if (strcmp(mode_str, "rerequest_irq") == 0) {
- int ret;
- GTP_ERROR("rerequest_irq, touch_irq = %d, irq_flag = %d",
- (int)touch_irq, irq_flag);
- free_irq(touch_irq, NULL);
- ret = tpd_irq_registration();
- if (ret < 0)
- GTP_ERROR("rerequest_irq fail, %d!", ret);
- } else if (strcmp(mode_str, "eint_dump_status") == 0) {
- GTP_ERROR("eint_dump_status, %u", touch_irq);
- /*mt_eint_dump_status(1);*/
- }
- return -1;
- }
- static u16 convert_productname(u8 *name)
- {
- int i;
- u16 product = 0;
- for (i = 0; i < 4; i++) {
- product <<= 4;
- if (name[i] < '0' || name[i] > '9')
- product += '*';
- else
- product += name[i] - '0';
- }
- return product;
- }
- static int tpd_i2c_remove(struct i2c_client *client)
- {
- gt1x_deinit();
- return 0;
- }
- static int tpd_local_init(void)
- {
- #if !defined CONFIG_MTK_LEGACY
- int ret;
- GTP_INFO("Device Tree get regulator!");
- tpd->reg = regulator_get(tpd->tpd_dev, "vtouch");
- ret = regulator_set_voltage(tpd->reg, 2800000, 2800000); /*set 2.8v*/
- if (ret) {
- GTP_ERROR("regulator_set_voltage(%d) failed!\n", ret);
- return -1;
- }
- #endif
- #ifdef TPD_POWER_SOURCE_CUSTOM
- #ifdef CONFIG_ARCH_MT6580
- tpd->reg = regulator_get(tpd->tpd_dev, "VGP1"); /*get pointer to regulator structure*/
- if (IS_ERR(tpd->reg))
- GTP_ERROR("regulator_get() failed!\n");
- #endif
- #endif
- #if TPD_SUPPORT_I2C_DMA
- tpd->dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
- gpDMABuf_va = (u8 *) dma_alloc_coherent(&tpd->dev->dev, IIC_DMA_MAX_TRANSFER_SIZE,
- &gpDMABuf_pa, GFP_KERNEL);
- if (!gpDMABuf_va) {
- GTP_ERROR("Allocate DMA I2C Buffer failed!");
- return -1;
- }
- memset(gpDMABuf_va, 0, IIC_DMA_MAX_TRANSFER_SIZE);
- #endif
- spin_lock_init(&irq_flag_lock);
- if (i2c_add_driver(&tpd_i2c_driver) != 0) {
- GTP_ERROR("unable to add i2c driver.");
- return -1;
- }
- if (tpd_load_status == 0) { /*disable auto load touch driver for linux3.0 porting*/
- GTP_ERROR("add error touch panel driver.");
- i2c_del_driver(&tpd_i2c_driver);
- return -1;
- }
- input_set_abs_params(tpd->dev, ABS_MT_TRACKING_ID, 0, (GTP_MAX_TOUCH - 1), 0, 0);
- if (tpd_dts_data.use_tpd_button) {
- /*initialize tpd button data*/
- tpd_button_setting(tpd_dts_data.tpd_key_num, tpd_dts_data.tpd_key_local,
- tpd_dts_data.tpd_key_dim_local);
- }
- #if (defined(TPD_WARP_START) && defined(TPD_WARP_END))
- TPD_DO_WARP = 1;
- memcpy(tpd_wb_start, tpd_wb_start_local, TPD_WARP_CNT * 4);
- memcpy(tpd_wb_end, tpd_wb_start_local, TPD_WARP_CNT * 4);
- #endif
- #if (defined(TPD_HAVE_CALIBRATION) && !defined(TPD_CUSTOM_CALIBRATION))
- memcpy(tpd_calmat, tpd_def_calmat_local, 8 * 4);
- memcpy(tpd_def_calmat, tpd_def_calmat_local, 8 * 4);
- #endif
- /*set vendor string*/
- tpd->dev->id.vendor = 0x00;
- tpd->dev->id.product = convert_productname(gt1x_version.product_id);
- tpd->dev->id.version = (gt1x_version.patch_id >> 8);
- GTP_INFO("end %s, %d\n", __func__, __LINE__);
- tpd_type_cap = 1;
- return 0;
- }
- /* Function to manage low power suspend */
- static void tpd_suspend(struct device *h)
- {
- s32 ret = -1;
- #if defined(CONFIG_GTP_HOTKNOT)
- #ifndef CONFIG_HOTKNOT_BLOCK_RW
- u8 buf[1] = { 0 };
- #endif
- #endif
- GTP_INFO("TPD suspend start...");
- mutex_lock(&tui_lock);
- if (tpd_tui_flag) {
- GTP_INFO("[TPD] skip tpd_suspend due to TUI in used\n");
- tpd_tui_low_power_skipped = 1;
- mutex_unlock(&tui_lock);
- return;
- }
- mutex_unlock(&tui_lock);
- #ifdef CONFIG_GTP_PROXIMITY
- if (gt1x_proximity_flag == 1) {
- GTP_INFO("Suspend: proximity is detected!");
- return;
- }
- #endif
- #ifdef CONFIG_GTP_HOTKNOT
- if (hotknot_enabled) {
- #ifdef CONFIG_HOTKNOT_BLOCK_RW
- if (hotknot_paired_flag) {
- GTP_INFO("Suspend: hotknot is paired!");
- return;
- }
- #else
- gt1x_i2c_read(GTP_REG_HN_PAIRED, buf, sizeof(buf));
- GTP_DEBUG("0x81AA: 0x%02X", buf[0]);
- if (buf[0] == 0x55) {
- GTP_INFO("Suspend: hotknot is paired!");
- return;
- }
- #endif
- }
- #endif
- tpd_halt = 1;
- #ifdef CONFIG_GTP_ESD_PROTECT
- gt1x_esd_switch(SWITCH_OFF);
- #endif
- #ifdef CONFIG_GTP_CHARGER_SWITCH
- gt1x_charger_switch(SWITCH_OFF);
- #endif
- mutex_lock(&i2c_access);
- #ifdef CONFIG_GTP_GESTURE_WAKEUP
- gesture_clear_wakeup_data();
- if (gesture_enabled) {
- gesture_enter_doze();
- } else
- #endif
- {
- gt1x_irq_disable();
- ret = gt1x_enter_sleep();
- if (ret < 0)
- GTP_ERROR("GTP early suspend failed.");
- else
- gtp_suspend = true;
- }
- mutex_unlock(&i2c_access);
- msleep(58);
- }
- /* Function to manage power-on resume */
- static void tpd_resume(struct device *h)
- {
- s32 ret = -1;
- GTP_INFO("TPD resume start...");
- gtp_suspend = false;
- #ifdef CONFIG_GTP_PROXIMITY
- if (gt1x_proximity_flag == 1) {
- GTP_INFO("Resume: proximity is on!");
- return;
- }
- #endif
- #ifdef CONFIG_GTP_HOTKNOT
- if (hotknot_enabled) {
- #ifdef CONFIG_HOTKNOT_BLOCK_RW
- if (hotknot_paired_flag) {
- hotknot_paired_flag = 0;
- GTP_INFO("Resume: hotknot is paired!");
- return;
- }
- #endif
- }
- #endif
- ret = gt1x_wakeup_sleep();
- if (ret < 0)
- GTP_ERROR("GTP later resume failed.");
- #ifdef CONFIG_GTP_HOTKNOT
- if (!hotknot_enabled)
- gt1x_send_cmd(GTP_CMD_HN_EXIT_SLAVE, 0);
- #endif
- #ifdef CONFIG_GTP_CHARGER_SWITCH
- gt1x_charger_config(0);
- gt1x_charger_switch(SWITCH_ON);
- #endif
- tpd_halt = 0;
- gt1x_irq_enable();
- #ifdef CONFIG_GTP_ESD_PROTECT
- gt1x_esd_switch(SWITCH_ON);
- #endif
- GTP_DEBUG("tpd resume end.");
- }
- static struct tpd_driver_t tpd_device_driver = {
- .tpd_device_name = "gt9xx",
- .tpd_local_init = tpd_local_init,
- .suspend = tpd_suspend,
- .resume = tpd_resume,
- };
- int tpd_enter_tui(void)
- {
- int ret = 0;
- tpd_tui_flag = 1;
- mt_eint_set_deint(10, 187);
- GTP_INFO("[%s] enter tui", __func__);
- return ret;
- }
- int tpd_exit_tui(void)
- {
- int ret = 0;
- GTP_INFO("[%s] exit TUI+", __func__);
- mutex_lock(&tui_lock);
- tpd_tui_flag = 0;
- mutex_unlock(&tui_lock);
- if (tpd_tui_low_power_skipped) {
- tpd_tui_low_power_skipped = 0;
- GTP_INFO("[%s] do low power again+", __func__);
- tpd_suspend(NULL);
- GTP_INFO("[%s] do low power again-", __func__);
- }
- mt_eint_clr_deint(10);
- tpd_reregister_from_tui();
- GTP_INFO("[%s] exit TUI-", __func__);
- return ret;
- }
- void tpd_off(void)
- {
- gt1x_power_switch(SWITCH_OFF);
- tpd_halt = 1;
- gt1x_irq_disable();
- }
- void tpd_on(void)
- {
- s32 ret = -1, retry = 0;
- while (retry++ < 5) {
- ret = tpd_power_on();
- if (ret < 0)
- GTP_ERROR("I2C Power on ERROR!");
- ret = gt1x_send_cfg(gt1x_config, gt1x_cfg_length);
- if (ret == 0) {
- GTP_DEBUG("Wakeup sleep send gt1x_config success.");
- break;
- }
- }
- if (ret < 0)
- GTP_ERROR("GTP later resume failed.");
- tpd_halt = 0;
- }
- /* called when loaded into kernel */
- static int __init tpd_driver_init(void)
- {
- GTP_INFO("Goodix touch panel driver init.");
- tpd_get_dts_info();
- if (tpd_driver_add(&tpd_device_driver) < 0)
- GTP_INFO("add generic driver failed\n");
- return 0;
- }
- /* should never be called */
- static void __exit tpd_driver_exit(void)
- {
- GTP_INFO("MediaTek gt91xx touch panel driver exit\n");
- tpd_driver_remove(&tpd_device_driver);
- }
- module_init(tpd_driver_init);
- module_exit(tpd_driver_exit);
|