/* * MELFAS MIP4 Touchscreen * * Copyright (C) 2000-2018 MELFAS Inc. * * * mip4_ts.c * * Version : 2019.08.22 */ #include "mip4_ts.h" /* * Start-up run command */ int mip4_ts_startup_run(struct mip4_ts_info *info) { u8 wbuf[4]; dev_dbg(&info->client->dev, "%s [START]\n", __func__); wbuf[0] = MIP4_R0_CTRL; wbuf[1] = MIP4_R1_CTRL_RUN; wbuf[2] = 1; if (mip4_ts_i2c_write(info, wbuf, 3)) { dev_err(&info->client->dev, "%s [ERROR] mip4_ts_i2c_write\n", __func__); goto error; } dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return 0; error: dev_err(&info->client->dev, "%s [ERROR]\n", __func__); return 1; } /* * Start-up process */ int mip4_ts_startup(struct mip4_ts_info *info) { int ret = 0; dev_dbg(&info->client->dev, "%s [START]\n", __func__); #if 0 reinit_completion(&info->startup_done); dev_dbg(&info->client->dev, "%s - startup : reinit_completion\n", __func__); #else init_completion(&info->startup_done); dev_dbg(&info->client->dev, "%s - startup : init_completion\n", __func__); #endif mip4_ts_power_on(info, 30); if (!info->irq_enabled) { enable_irq(info->client->irq); info->irq_enabled = true; } /* Wait start-up interrupt */ dev_dbg(&info->client->dev, "%s - startup : wait_for_completion_interruptible_timeout[%d]\n", __func__, STARTUP_TIMEOUT); ret = wait_for_completion_interruptible_timeout(&info->startup_done, msecs_to_jiffies(STARTUP_TIMEOUT)); if (ret > 0) { dev_dbg(&info->client->dev, "%s - startup : completed[%d]\n", __func__, jiffies_to_msecs(ret)); } else { dev_dbg(&info->client->dev, "%s - startup : timeout[%d]\n", __func__, ret); #if USE_FW_RECOVERY /* Restore firmware */ dev_dbg(&info->client->dev, "%s - flash_fail_type : critical\n", __func__); ret = mip4_ts_fw_restore_critical_section(info); if (ret < 0) { dev_err(&info->client->dev, "%s [ERROR] mip4_ts_fw_restore_critical_section\n", __func__); } #endif /* USE_FW_RECOVERY */ } dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return 0; } /* * Reset chip */ void mip4_ts_reset(struct mip4_ts_info *info) { dev_dbg(&info->client->dev, "%s [START]\n", __func__); mip4_ts_power_off(info, POWER_OFF_DELAY); mip4_ts_power_on(info, POWER_ON_DELAY); dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); } /* * Restart chip */ void mip4_ts_restart(struct mip4_ts_info *info) { dev_dbg(&info->client->dev, "%s [START]\n", __func__); mip4_ts_power_off(info, POWER_OFF_DELAY); #if USE_STARTUP_WAITING mip4_ts_startup(info); #else mip4_ts_power_on(info, POWER_ON_DELAY); #endif /* USE_STARTUP_WAITING */ dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); } /* * I2C Read */ int mip4_ts_i2c_read(struct mip4_ts_info *info, char *write_buf, unsigned int write_len, char *read_buf, unsigned int read_len) { int retry = I2C_RETRY_COUNT; int res; struct i2c_msg msg[] = { { .addr = info->client->addr, .flags = 0, .buf = write_buf, .len = write_len, }, { .addr = info->client->addr, .flags = I2C_M_RD, .buf = read_buf, .len = read_len, }, }; while (retry--) { res = i2c_transfer(info->client->adapter, msg, ARRAY_SIZE(msg)); if (res == ARRAY_SIZE(msg)) { goto exit; } else if (res < 0) { dev_err(&info->client->dev, "%s [ERROR] i2c_transfer - errno[%d]\n", __func__, res); } else { dev_err(&info->client->dev, "%s [ERROR] i2c_transfer - size[%zu] result[%d]\n", __func__, ARRAY_SIZE(msg), res); } } goto error_reboot; error_reboot: #if RESET_ON_I2C_ERROR //mip4_ts_restart(info); #endif /* RESET_ON_I2C_ERROR */ return 1; exit: return 0; } /* * I2C Write */ int mip4_ts_i2c_write(struct mip4_ts_info *info, char *write_buf, unsigned int write_len) { int retry = I2C_RETRY_COUNT; int res; while (retry--) { res = i2c_master_send(info->client, write_buf, write_len); if (res == write_len) { goto exit; } else if (res < 0) { dev_err(&info->client->dev, "%s [ERROR] i2c_master_send - errno [%d]\n", __func__, res); } else { dev_err(&info->client->dev, "%s [ERROR] i2c_master_send - write[%d] result[%d]\n", __func__, write_len, res); } } goto error_reboot; error_reboot: #if RESET_ON_I2C_ERROR //mip4_ts_restart(info); #endif /* RESET_ON_I2C_ERROR */ return 1; exit: return 0; } /* * Enable device */ int mip4_ts_enable(struct mip4_ts_info *info) { dev_dbg(&info->client->dev, "%s [START]\n", __func__); #if 0 if (info->enabled) { dev_warn(&info->client->dev, "%s - Device is already enabled\n", __func__); goto exit; } #else if (info->init) { mip4_ts_power_off(info, POWER_OFF_DELAY); mip4_ts_power_on(info, POWER_ON_DELAY); #if USE_LPM #if USE_STARTUP_WAITING mip4_ts_startup(info); #else if (!info->irq_enabled) { enable_irq(info->client->irq); info->irq_enabled = true; } #endif /* USE_STARTUP_WAITING */ #endif /* USE_LPM */ info->init = false; } else { if (info->enabled) { dev_warn(&info->client->dev, "%s - Device is already enabled\n", __func__); goto exit; } } #endif mutex_lock(&info->lock); mip4_ts_clear_input(info); #if USE_LPM #if 1 mip4_ts_set_power_state(info, MIP4_CTRL_POWER_ACTIVE); #else mip4_ts_restart(info); #endif #if USE_WAKELOCK if (wake_lock_active(&info->wake_lock)) { wake_unlock(&info->wake_lock); dev_dbg(&info->client->dev, "%s - wake_unlock\n", __func__); } #endif /* USE_WAKELOCK */ info->low_power_mode = false; dev_dbg(&info->client->dev, "%s - low power mode : off\n", __func__); #if USE_WAKEUP_GESTURE info->gesture_wakeup_mode = false; dev_dbg(&info->client->dev, "%s - gesture wake-up mode : off\n", __func__); #endif /* USE_WAKEUP_GESTURE */ #else /* USE_LPM */ #if USE_STARTUP_WAITING mip4_ts_startup(info); #else mip4_ts_power_on(info, POWER_ON_DELAY); if (!info->irq_enabled) { enable_irq(info->client->irq); info->irq_enabled = true; } #endif /* USE_STARTUP_WAITING */ #endif /* USE_LPM */ info->enabled = true; info->i2c_error_cnt = 0; mutex_unlock(&info->lock); exit: dev_info(&info->client->dev, MIP4_TS_DEVICE_NAME" - Enabled\n"); dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return 0; } /* * Disable device */ int mip4_ts_disable(struct mip4_ts_info *info) { struct timeval current_time; u32 time_val = 0; dev_dbg(&info->client->dev, "%s [START]\n", __func__); if (!info->enabled) { dev_warn(&info->client->dev, "%s - Device is already disabled\n", __func__); goto exit; } mutex_lock(&info->lock); #if USE_LPM #if USE_WAKEUP_GESTURE info->wakeup_gesture_code = 0; mip4_ts_set_wakeup_gesture_type(info, MIP4_EVENT_GESTURE_ALL); #endif /* USE_WAKEUP_GESTURE */ do_gettimeofday(¤t_time); time_val = (u32)current_time.tv_sec; mip4_ts_set_power_state(info, MIP4_CTRL_POWER_LOW); info->low_power_mode = true; dev_dbg(&info->client->dev, "%s - low power mode : on\n", __func__); #if 0 // USE_SPONGE mip4_ts_sponge_write_time(info, time_val); #endif #if USE_WAKEUP_GESTURE info->gesture_wakeup_mode = true; dev_dbg(&info->client->dev, "%s - gesture wake-up mode : on\n", __func__); #endif /* USE_WAKEUP_GESTURE */ #if USE_WAKELOCK if (!wake_lock_active(&info->wake_lock)) { wake_lock(&info->wake_lock); dev_dbg(&info->client->dev, "%s - wake_lock\n", __func__); } #endif /* USE_WAKELOCK */ #else /* USE_LPM */ disable_irq(info->client->irq); info->irq_enabled = false; mip4_ts_power_off(info, POWER_OFF_DELAY); #endif /* USE_LPM */ mip4_ts_clear_input(info); info->enabled = false; mutex_unlock(&info->lock); exit: dev_info(&info->client->dev, MIP4_TS_DEVICE_NAME" - Disabled\n"); dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return 0; } #if USE_FB_NOTIFY /* * FB notifier callback */ static int mip4_ts_fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data) { struct mip4_ts_info *info = container_of(self, struct mip4_ts_info, fb_notifier); struct fb_event *event_data = data; unsigned int blank; dev_dbg(&info->client->dev, "%s [START]\n", __func__); /* Check event */ //if (event != FB_EARLY_EVENT_BLANK) { if (event != FB_EVENT_BLANK) { dev_dbg(&info->client->dev, "%s - skip event [0x%02X]\n", __func__, event); goto exit; } /* Check blank */ blank = *(int *)event_data->data; dev_dbg(&info->client->dev, "%s - blank[0x%02X]\n", __func__, blank); switch (blank) { case FB_BLANK_UNBLANK: /* Enable */ dev_dbg(&info->client->dev, "%s - FB_BLANK_UNBLANK\n", __func__); break; case FB_BLANK_POWERDOWN: /* Disable */ dev_dbg(&info->client->dev, "%s - FB_BLANK_POWERDOWN\n", __func__); break; default: dev_dbg(&info->client->dev, "%s - skip blank [0x%02X]\n", __func__, blank); break; } exit: dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return 0; } #endif /* USE_FB_NOTIFY */ #if USE_INPUT_OPEN_CLOSE /* * Open input device */ static int mip4_ts_input_open(struct input_dev *dev) { struct mip4_ts_info *info = input_get_drvdata(dev); dev_dbg(&info->client->dev, "%s [START]\n", __func__); #if 0 if (info->init == true) { mip4_ts_restart(info); info->init = false; } else { mip4_ts_enable(info); } #else mip4_ts_enable(info); #endif dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return 0; } /* * Close input device */ static void mip4_ts_input_close(struct input_dev *dev) { struct mip4_ts_info *info = input_get_drvdata(dev); dev_dbg(&info->client->dev, "%s [START]\n", __func__); mip4_ts_disable(info); dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); } #endif /* USE_INPUT_OPEN_CLOSE */ /* * Get ready status */ int mip4_ts_get_ready_status(struct mip4_ts_info *info) { u8 wbuf[16]; u8 rbuf[16]; int ret = 0; //dev_dbg(&info->client->dev, "%s [START]\n", __func__); wbuf[0] = MIP4_R0_CTRL; wbuf[1] = MIP4_R1_CTRL_READY_STATUS; if (mip4_ts_i2c_read(info, wbuf, 2, rbuf, 1)) { dev_err(&info->client->dev, "%s [ERROR] mip4_ts_i2c_read\n", __func__); goto error; } ret = rbuf[0]; /* Check status */ if ((ret == MIP4_CTRL_STATUS_NONE) || (ret == MIP4_CTRL_STATUS_LOG) || (ret == MIP4_CTRL_STATUS_READY)) { //dev_dbg(&info->client->dev, "%s - status[0x%02X]\n", __func__, ret); } else { dev_err(&info->client->dev, "%s [ERROR] Unknown status[0x%02X]\n", __func__, ret); goto error; } if (ret == MIP4_CTRL_STATUS_LOG) { /* Skip log event */ wbuf[0] = MIP4_R0_LOG; wbuf[1] = MIP4_R1_LOG_TRIGGER; wbuf[2] = 0; if (mip4_ts_i2c_write(info, wbuf, 3)) { dev_err(&info->client->dev, "%s [ERROR] mip4_ts_i2c_write\n", __func__); } } //dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return ret; error: dev_err(&info->client->dev, "%s [ERROR]\n", __func__); return 1; } /* * Read chip firmware version */ int mip4_ts_get_fw_version(struct mip4_ts_info *info, u8 *ver_buf) { u8 rbuf[8]; u8 wbuf[2]; int i; wbuf[0] = MIP4_R0_INFO; wbuf[1] = MIP4_R1_INFO_VERSION_BOOT; if (mip4_ts_i2c_read(info, wbuf, 2, rbuf, 8)) { goto error; }; for (i = 0; i < 8; i++) { ver_buf[i] = rbuf[i]; } return 0; error: for (i = 0; i < 8; i++) { ver_buf[i] = 0xFF; } dev_err(&info->client->dev, "%s [ERROR]\n", __func__); return 1; } /* * Read chip firmware version for u16 */ int mip4_ts_get_fw_version_u16(struct mip4_ts_info *info, u16 *ver_buf_u16) { u8 rbuf[8]; int i; if (mip4_ts_get_fw_version(info, rbuf)) { goto error; } for (i = 0; i < 4; i++) { ver_buf_u16[i] = (rbuf[i * 2 + 1] << 8) | rbuf[i * 2]; } return 0; error: for (i = 0; i < 4; i++) { ver_buf_u16[i] = 0xFFFF; } dev_err(&info->client->dev, "%s [ERROR]\n", __func__); return 1; } #if (CHIP_MODEL != CHIP_NONE) /* * Read bin(file) firmware version */ int mip4_ts_get_fw_version_from_bin(struct mip4_ts_info *info, u8 *ver_buf) { const struct firmware *fw; int i; dev_dbg(&info->client->dev, "%s [START]\n", __func__); request_firmware(&fw, FW_PATH_INTERNAL, &info->client->dev); if (!fw) { dev_err(&info->client->dev, "%s [ERROR] request_firmware\n", __func__); goto error; } if (mip4_ts_bin_fw_version(info, fw->data, fw->size, ver_buf)) { for (i = 0; i < (4 * 2); i++) { ver_buf[i] = 0xFF; } dev_err(&info->client->dev, "%s [ERROR] mip4_ts_bin_fw_version\n", __func__); goto error; } release_firmware(fw); dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return 0; error: dev_err(&info->client->dev, "%s [ERROR]\n", __func__); return 1; } #endif /* CHIP_MODEL */ /* * Set power state */ int mip4_ts_set_power_state(struct mip4_ts_info *info, u8 mode) { u8 wbuf[3]; dev_dbg(&info->client->dev, "%s [START]\n", __func__); dev_dbg(&info->client->dev, "%s - mode[%u]\n", __func__, mode); wbuf[0] = MIP4_R0_CTRL; wbuf[1] = MIP4_R1_CTRL_POWER_STATE; wbuf[2] = mode; if (mip4_ts_i2c_write(info, wbuf, 3)) { dev_err(&info->client->dev, "%s [ERROR] mip4_ts_i2c_write\n", __func__); goto error; } dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return 0; error: dev_err(&info->client->dev, "%s [ERROR]\n", __func__); return 1; } /* * Set wake-up gesture type */ int mip4_ts_set_wakeup_gesture_type(struct mip4_ts_info *info, u32 type) { u8 wbuf[6]; dev_dbg(&info->client->dev, "%s [START]\n", __func__); dev_dbg(&info->client->dev, "%s - type[%08X]\n", __func__, type); wbuf[0] = MIP4_R0_CTRL; wbuf[1] = MIP4_R1_CTRL_GESTURE_TYPE; wbuf[2] = (type >> 24) & 0xFF; wbuf[3] = (type >> 16) & 0xFF; wbuf[4] = (type >> 8) & 0xFF; wbuf[5] = type & 0xFF; if (mip4_ts_i2c_write(info, wbuf, 6)) { dev_err(&info->client->dev, "%s [ERROR] mip4_ts_i2c_write\n", __func__); goto error; } dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return 0; error: dev_err(&info->client->dev, "%s [ERROR]\n", __func__); return 1; } /* * Disable ESD alert */ int mip4_ts_disable_esd_alert(struct mip4_ts_info *info) { u8 wbuf[4]; u8 rbuf[4]; dev_dbg(&info->client->dev, "%s [START]\n", __func__); wbuf[0] = MIP4_R0_CTRL; wbuf[1] = MIP4_R1_CTRL_DISABLE_ESD_ALERT; wbuf[2] = 1; if (mip4_ts_i2c_write(info, wbuf, 3)) { dev_err(&info->client->dev, "%s [ERROR] mip4_ts_i2c_write\n", __func__); goto error; } if (mip4_ts_i2c_read(info, wbuf, 2, rbuf, 1)) { dev_err(&info->client->dev, "%s [ERROR] mip4_ts_i2c_read\n", __func__); goto error; } if (rbuf[0] != 1) { dev_dbg(&info->client->dev, "%s [ERROR] failed\n", __func__); goto error; } dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return 0; error: dev_err(&info->client->dev, "%s [ERROR]\n", __func__); return 1; } /* * Alert event handler - ESD */ static int mip4_ts_alert_handler_esd(struct mip4_ts_info *info, u8 *rbuf) { u8 frame_cnt = rbuf[1]; dev_dbg(&info->client->dev, "%s [START]\n", __func__); dev_dbg(&info->client->dev, "%s - frame_cnt[%d]\n", __func__, frame_cnt); if (frame_cnt == 0) { /* Panel defect, not ESD */ info->esd_cnt++; dev_dbg(&info->client->dev, "%s - esd_cnt[%d]\n", __func__, info->esd_cnt); if (info->disable_esd == true) { mip4_ts_disable_esd_alert(info); info->esd_cnt = 0; } else if (info->esd_cnt > ESD_COUNT_FOR_DISABLE) { if (!mip4_ts_disable_esd_alert(info)) { info->disable_esd = true; info->esd_cnt = 0; } } else { mip4_ts_restart(info); } } else { /* ESD detected */ info->esd_cnt = 0; mip4_ts_restart(info); } dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return 0; } /* * Alert event handler - Wake-up */ static int mip4_ts_alert_handler_wakeup(struct mip4_ts_info *info, u8 *rbuf) { int gesture_code = rbuf[1]; dev_dbg(&info->client->dev, "%s [START]\n", __func__); if (mip4_ts_gesture_wakeup_event_handler(info, gesture_code)) { goto error; } dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return 0; error: dev_err(&info->client->dev, "%s [ERROR]\n", __func__); return 1; } /* * Alert event handler - Input type */ static int mip4_ts_alert_handler_inputtype(struct mip4_ts_info *info, u8 *rbuf) { u8 input_type = rbuf[1]; dev_dbg(&info->client->dev, "%s [START]\n", __func__); switch (input_type) { case 0: dev_dbg(&info->client->dev, "%s - Input type : Finger\n", __func__); break; case 1: dev_dbg(&info->client->dev, "%s - Input type : Glove\n", __func__); break; default: dev_err(&info->client->dev, "%s - Input type : Unknown[%d]\n", __func__, input_type); goto error; } dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return 0; error: dev_err(&info->client->dev, "%s [ERROR]\n", __func__); return 1; } /* * Alert event handler - Image */ static int mip4_ts_alert_handler_image(struct mip4_ts_info *info, u8 *rbuf) { u8 image_type = rbuf[1]; dev_dbg(&info->client->dev, "%s [START]\n", __func__); switch (image_type) { #if USE_WAKEUP_GESTURE case MIP4_IMG_TYPE_GESTURE: if (mip4_ts_gesture_wakeup_event_handler(info, 1)) { dev_err(&info->client->dev, "%s [ERROR] mip4_ts_wakeup_event_handler\n", __func__); goto error; } if (mip4_ts_get_image(info, rbuf[1])) { dev_err(&info->client->dev, "%s [ERROR] mip4_ts_get_image\n", __func__); goto error; } break; #endif /* USE_WAKEUP_GESTURE */ default: goto error; } dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return 0; error: dev_err(&info->client->dev, "%s [ERROR]\n", __func__); return 1; } /* * Alert event handler - Flash failure */ int mip4_ts_alert_handler_flash(struct mip4_ts_info *info, u8 *data) { #if USE_FW_RECOVERY int ret = 0; int retry = 1; u8 sections[64]; int i_byte = 0; int i_bit = 0; dev_dbg(&info->client->dev, "%s [START]\n", __func__); print_hex_dump(KERN_ERR, MIP4_TS_DEVICE_NAME " Sections : ", DUMP_PREFIX_OFFSET, 16, 1, data, 8, false); for (i_byte = 0; i_byte < 8; i_byte++) { dev_info(&info->client->dev, "%s - packet #%d [0x%02X]\n", __func__, i_byte, data[i_byte]); for (i_bit = 0; i_bit < 8; i_bit++) { sections[i_byte * 8 + i_bit] = (data[i_byte] >> i_bit) & 0x01; dev_info(&info->client->dev, "%s - section #%d [%d]\n", __func__, i_byte * 8 + i_bit, sections[i_byte * 8 + i_bit]); } } ret = mip4_ts_fw_restore_from_kernel(info, sections, retry); if (ret < FW_ERR_NONE) { dev_err(&info->client->dev, "%s - fw_err[%d]\n", __func__, ret); goto error; } dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return 0; error: dev_err(&info->client->dev, "%s [ERROR]\n", __func__); return 1; #else return 0; #endif /* USE_FW_RECOVERY */ } /* * Alert event handler - SRAM failure */ static int mip4_ts_alert_handler_sram(struct mip4_ts_info *info, u8 *data) { int i; dev_dbg(&info->client->dev, "%s [START]\n", __func__); info->sram_addr_num = (unsigned int) (data[0] | (data[1] << 8)); dev_info(&info->client->dev, "%s - sram_addr_num [%d]\n", __func__, info->sram_addr_num); if (info->sram_addr_num > 8) { dev_err(&info->client->dev, "%s [ERROR] sram_addr_num [%d]\n", __func__, info->sram_addr_num); goto error; } for (i = 0; i < info->sram_addr_num; i++) { info->sram_addr[i] = data[2 + 4 * i] | (data[2 + 4 * i + 1] << 8) | (data[2 + 4 * i + 2] << 16) | (data[2 + 4 * i + 3] << 24); dev_info(&info->client->dev, "%s - sram_addr #%d [0x%08X]\n", __func__, i, info->sram_addr[i]); } for (i = info->sram_addr_num; i < 8; i++) { info->sram_addr[i] = 0; dev_info(&info->client->dev, "%s - sram_addr #%d [0x%08X]\n", __func__, i, info->sram_addr[i]); } dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return 0; error: dev_err(&info->client->dev, "%s [ERROR]\n", __func__); return 1; } /* * Alert event handler - Custom */ static int __maybe_unused mip4_ts_alert_handler_f1(struct mip4_ts_info *info, u8 *rbuf, u8 size) { dev_dbg(&info->client->dev, "%s [START]\n", __func__); #if 0 if (rbuf[1] == 2) { if (mip4_ts_custom_event_handler(info, rbuf, size)) { dev_err(&info->client->dev, "%s [ERROR]\n", __func__); } } #endif dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return 0; } /* * Interrupt handler */ static irqreturn_t __maybe_unused mip4_ts_interrupt(int irq, void *dev_id) { struct mip4_ts_info *info = dev_id; u8 wbuf[8]; u8 rbuf[256]; unsigned int size = 0; u8 category = 0; u8 alert_type = 0; bool startup = false; u8 flash_fail_type = FLASH_FAIL_NONE; dev_dbg(&info->client->dev, "%s [START]\n", __func__); #if USE_STARTUP_WAITING /* Start-up interrupt */ if (info->startup_init == false) { dev_dbg(&info->client->dev, "%s - skip\n", __func__); goto exit; } if (!completion_done(&info->startup_done)) { startup = true; dev_dbg(&info->client->dev, "%s - start-up\n", __func__); } #endif /* USE_STARTUP_WAITING */ /* Read packet info */ wbuf[0] = MIP4_R0_EVENT; wbuf[1] = MIP4_R1_EVENT_PACKET_INFO; if (mip4_ts_i2c_read(info, wbuf, 2, rbuf, 1)) { dev_err(&info->client->dev, "%s [ERROR] Read packet info\n", __func__); if (!startup) { info->i2c_error_cnt++; goto error; } else { flash_fail_type = FLASH_FAIL_CRITICAL; goto startup_exit; } } size = (rbuf[0] & 0x7F); category = ((rbuf[0] >> 7) & 0x1); if (info->event_size_type == 1 && category == 0) size = info->event_size * size; dev_dbg(&info->client->dev, "%s - packet info : size_type[%d] size[%d] category[%d]\n", __func__, info->event_size_type, size, category); /* Check packet size */ if ((size <= 0) || (size > 200)) { dev_err(&info->client->dev, "%s [ERROR] Packet size [%d]\n", __func__, size); if (!startup) { info->i2c_error_cnt++; goto error; } else { flash_fail_type = FLASH_FAIL_CRITICAL; goto startup_exit; } } /* Read packet data */ wbuf[0] = MIP4_R0_EVENT; wbuf[1] = MIP4_R1_EVENT_PACKET_DATA; if (mip4_ts_i2c_read(info, wbuf, 2, rbuf, size)) { dev_err(&info->client->dev, "%s [ERROR] Read packet data\n", __func__); if (!startup) { info->i2c_error_cnt++; goto error; } else { flash_fail_type = FLASH_FAIL_CRITICAL; goto startup_exit; } } /* Event handler */ if (startup == false) { if (category == 0) { /* Input event */ info->esd_cnt = 0; mip4_ts_input_event_handler(info, size, rbuf); } else { /* Alert event */ alert_type = rbuf[0]; dev_dbg(&info->client->dev, "%s - alert type[%d]\n", __func__, alert_type); switch (alert_type) { case MIP4_ALERT_ESD: if (mip4_ts_alert_handler_esd(info, rbuf)) { goto error; } break; case MIP4_ALERT_WAKEUP: if (mip4_ts_alert_handler_wakeup(info, rbuf)) { goto error; } break; case MIP4_ALERT_INPUT_TYPE: if (mip4_ts_alert_handler_inputtype(info, rbuf)) { goto error; } break; case MIP4_ALERT_IMAGE: if (mip4_ts_alert_handler_image(info, rbuf)) { goto error; } break; case MIP4_ALERT_FLASH_FAILURE: if (mip4_ts_alert_handler_flash(info, &rbuf[1])) { goto error; } break; case MIP4_ALERT_SRAM_FAILURE: if (mip4_ts_alert_handler_sram(info, &rbuf[1])) { goto error; } break; case MIP4_ALERT_BOOT_SUCCEEDED: mip4_ts_startup_config(info); mip4_ts_startup_run(info); break; case MIP4_ALERT_F1: if (mip4_ts_alert_handler_f1(info, rbuf, size)) { goto error; } break; default: dev_err(&info->client->dev, "%s [ERROR] Unknown alert type[%d]\n", __func__, alert_type); goto error; } } } else { #if USE_STARTUP_WAITING /* Start-up */ if (category == 1) { alert_type = rbuf[0]; dev_dbg(&info->client->dev, "%s - alert type[%d]\n", __func__, alert_type); switch (alert_type) { case MIP4_ALERT_FLASH_FAILURE: flash_fail_type = FLASH_FAIL_SECTION; break; case MIP4_ALERT_BOOT_SUCCEEDED: flash_fail_type = FLASH_FAIL_NONE; break; default: dev_err(&info->client->dev, "%s [ERROR] Unknown alert type[%d]\n", __func__, alert_type); flash_fail_type = FLASH_FAIL_CRITICAL; break; } } else { dev_err(&info->client->dev, "%s [ERROR] Unknown catetory[%d]\n", __func__, category); flash_fail_type = FLASH_FAIL_CRITICAL; } goto startup_exit; #endif /* USE_STARTUP_WAITING */ } #if USE_STARTUP_WAITING exit: #endif /* USE_STARTUP_WAITING */ info->i2c_error_cnt = 0; dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return IRQ_HANDLED; startup_exit: #if USE_STARTUP_WAITING complete_all(&info->startup_done); dev_dbg(&info->client->dev, "%s - startup : complete_all\n", __func__); if (alert_type == MIP4_ALERT_BOOT_SUCCEEDED) { mip4_ts_startup_config(info); mip4_ts_startup_run(info); } #if USE_FW_RECOVERY if (flash_fail_type == FLASH_FAIL_CRITICAL) { mip4_ts_fw_restore_critical_section(info); } else if (flash_fail_type == FLASH_FAIL_SECTION) { mip4_ts_alert_handler_flash(info, &rbuf[1]); } #endif /* USE_FW_RECOVERY */ #endif /* USE_STARTUP_WAITING */ dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return IRQ_HANDLED; error: #if RESET_ON_EVENT_ERROR //dev_err(&info->client->dev, "%s - Reset on event error\n", __func__); //mip4_ts_restart(info); #endif /* RESET_ON_EVENT_ERROR */ #if USE_STARTUP_WAITING #endif /* USE_STARTUP_WAITING */ #if USE_FW_RECOVERY if (info->i2c_error_cnt >= I2C_ERR_CNT_FOR_FW_RECOVERY) { mip4_ts_fw_restore_critical_section(info); } #endif /* USE_FW_RECOVERY */ dev_err(&info->client->dev, "%s [ERROR]\n", __func__); return IRQ_HANDLED; } /* * Config module */ int mip4_ts_config(struct mip4_ts_info *info) { u8 wbuf[4]; u8 rbuf[16]; int ret = 0; int retry = I2C_RETRY_COUNT; int tmp; dev_dbg(&info->client->dev, "%s [START]\n", __func__); /* Product name */ wbuf[0] = MIP4_R0_INFO; wbuf[1] = MIP4_R1_INFO_PRODUCT_NAME; ret = mip4_ts_i2c_read(info, wbuf, 2, rbuf, 16); if (ret) { dev_err(&info->client->dev, "%s [ERROR] mip4_ts_i2c_read\n", __func__); goto error; } memcpy(info->product_name, rbuf, 16); dev_dbg(&info->client->dev, "%s - product_name[%s]\n", __func__, info->product_name); /* Firmware version */ ret = mip4_ts_get_fw_version(info, rbuf); if (ret) { dev_err(&info->client->dev, "%s [ERROR] mip4_ts_i2c_read\n", __func__); goto error; } memcpy(info->fw_version, rbuf, 8); dev_info(&info->client->dev, "%s - F/W Version : %02X.%02X / %02X.%02X.%02X.%02X / %02X.%02X\n", __func__, info->fw_version[0], info->fw_version[1], info->fw_version[2], info->fw_version[3], info->fw_version[4], info->fw_version[5], info->fw_version[6], info->fw_version[7]); /* Resolution */ wbuf[0] = MIP4_R0_INFO; wbuf[1] = MIP4_R1_INFO_RESOLUTION_X; retry = 10; while (retry--){ if (mip4_ts_i2c_read(info, wbuf, 2, rbuf, 14)){ dev_err(&info->client->dev, "%s [ERROR] mip4_ts_i2c_read\n", __func__); } else { tmp = (rbuf[4] & rbuf[5]) | rbuf[6]; if (0 == (rbuf[0]) | (rbuf[1] << 8) || 0xFFFF == (rbuf[0]) | (rbuf[1] << 8) || 0 == (rbuf[2]) | (rbuf[3] << 8) || 0xFFFF == (rbuf[2]) | (rbuf[3] << 8) || 0 == tmp || 0xFF == tmp) { dev_err(&info->client->dev, "%s: Fail to read tsp info[%x,%x,%x,%x,%x,%x,%x]\n", __func__, rbuf[0], rbuf[1], rbuf[2], rbuf[3], rbuf[4], rbuf[5], rbuf[6]); msleep(20); continue; } break; } } if (retry <= 0) { dev_err(&info->client->dev, "%s [ERROR] Resolution - retry limit\n", __func__); //////////////////////////////////////////////////// // PLEASE MODIFY HERE (default value) !!! // resolution_x / y, node_x / y / key // // //////////////////////////////////////////////////// info->max_x = 4095; info->max_y = 4095; info->node_x = 15; info->node_y = 33; info->node_key = 0; } else { info->max_x = (rbuf[0]) | (rbuf[1] << 8); info->max_y = (rbuf[2]) | (rbuf[3] << 8); dev_dbg(&info->client->dev, "%s - max_x[%d] max_y[%d]\n", __func__, info->max_x, info->max_y); info->ppm_x = rbuf[12]; info->ppm_y = rbuf[13]; dev_dbg(&info->client->dev, "%s - ppm_x[%d] ppm_y[%d]\n", __func__, info->ppm_x, info->ppm_y); /* Node info */ info->node_x = rbuf[4]; info->node_y = rbuf[5]; info->node_key = rbuf[6]; dev_dbg(&info->client->dev, "%s - node_x[%d] node_y[%d] node_key[%d]\n", __func__, info->node_x, info->node_y, info->node_key); } /* Key info */ if (info->node_key > 0) { /* Enable touchkey */ info->key_enable = true; info->key_num = info->node_key; } /* Protocol */ wbuf[0] = MIP4_R0_EVENT; wbuf[1] = MIP4_R1_EVENT_FORMAT; retry = 10; while (retry--) { if (mip4_ts_i2c_read(info, wbuf, 2, rbuf, 4)) { dev_err(&info->client->dev, "%s [ERROR] mip4_ts_i2c_read - event format\n", __func__); } else { info->event_format = (int)(rbuf[0] | (rbuf[1] << 8)); switch (info->event_format) { case 0: case 1: case 3: case 4: case 8: case 10: break; default: dev_err(&info->client->dev, "%s [ERROR] event_format[%d]\n", __func__, info->event_format); continue; } info->event_size = rbuf[2]; if (info->event_size <= 0 || rbuf[2] == 0xFF) { dev_err(&info->client->dev, "%s [ERROR] event_size[%d]\n", __func__, info->event_size); continue; } info->event_size_type = (rbuf[3] & 0x01); dev_dbg(&info->client->dev, "%s - event_format[%d] event_size[%d], event_size_type[%d]\n", __func__, info->event_format, info->event_size, info->event_size_type); break; } } if (retry <= 0) { dev_err(&info->client->dev, "%s [ERROR] event format - retry limit\n", __func__); //////////////////////////////////////////////////// // PLEASE MODIFY HERE (default value) !!! // event_format / event_size // // //////////////////////////////////////////////////// } dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return 0; error: dev_err(&info->client->dev, "%s [ERROR]\n", __func__); return 1; } /* * Config platform */ static int mip4_ts_config_platform(struct mip4_ts_info *info) { //#ifdef CONFIG_ACPI #if 0 struct acpi_device *a_dev; acpi_status a_status; #endif /* CONFIG_ACPI */ int ret = 0; dev_dbg(&info->client->dev, "%s [START]\n", __func__); //#ifdef CONFIG_ACPI #if 0 /* ACPI */ dev_dbg(&info->client->dev, "%s - ACPI\n", __func__); a_status = acpi_bus_get_device(ACPI_HANDLE(&info->client->dev), &a_dev); if (ACPI_SUCCESS(a_status)) { if (strncmp(dev_name(&a_dev->dev), ACPI_ID, 8) != 0) { dev_err(&info->client->dev, "%s [ERROR] ACPI_ID mismatch [%s]\n", __func__, dev_name(&a_dev->dev)); ret = -EINVAL; goto exit; } } #else #ifdef CONFIG_OF /* Devicetree */ if (&info->client->dev.of_node) { dev_dbg(&info->client->dev, "%s - Devicetree\n", __func__); ret = mip4_ts_parse_devicetree(&info->client->dev, info); if (ret) { dev_err(&info->client->dev, "%s [ERROR] mip4_ts_parse_devicetree\n", __func__); goto exit; } } else { dev_err(&info->client->dev, "%s [ERROR] of_node\n", __func__); goto exit; } #else /* Platform device */ dev_dbg(&info->client->dev, "%s - Platform device\n", __func__); info->pdata = dev_get_platdata(&info->client->dev); if (info->pdata == NULL) { ret = -EINVAL; dev_err(&info->client->dev, "%s [ERROR] dev_get_platdata\n", __func__); goto exit; } info->gpio_intr = info->pdata->gpio_intr; info->gpio_ce = info->pdata->gpio_ce; info->gpio_vd33_en = info->pdata->gpio_vd33_en; ret = mip4_ts_config_gpio(info); if (ret) { dev_err(&info->client->dev, "%s [ERROR] mip4_ts_config_gpio\n", __func__); goto exit; } #endif /* CONFIG_OF */ #endif /* CONFIG_ACPI */ exit: dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return ret; } #if (CHIP_MODEL != CHIP_NONE) #if USE_FW_RECOVERY /* * Restore critical section of firmware from kernel built-in firmware file */ int mip4_ts_fw_restore_critical_section(struct mip4_ts_info *info) { int ret = 0; int i; u8 sections[FW_SECTION_NUM]; int retry = 1; dev_dbg(&info->client->dev, "%s [START]\n", __func__); /* Restore firmware */ memset(sections, 0, FW_SECTION_NUM); for (i = 0; i < FW_CRITICAL_SECTION_NUM; i++) { sections[i] = 1; } ret = mip4_ts_fw_restore_from_kernel(info, sections, retry); if (ret < 0) { dev_err(&info->client->dev, "%s [ERROR] mms_fw_restore_from_kernel\n", __func__); goto error; } dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return 0; error: dev_err(&info->client->dev, "%s [ERROR]\n", __func__); return 1; } /* * Restore firmware from kernel built-in firmware file */ int mip4_ts_fw_restore_from_kernel(struct mip4_ts_info *info, u8 *sections, int retry) { const char *fw_name = FW_PATH_INTERNAL; const struct firmware *fw; int ret = FW_ERR_NONE; dev_dbg(&info->client->dev, "%s [START]\n", __func__); //mutex_lock(&info->lock); mip4_ts_clear_input(info); print_hex_dump(KERN_ERR, MIP4_TS_DEVICE_NAME " Sections : ", DUMP_PREFIX_OFFSET, 16, 1, sections, FW_SECTION_NUM, false); /* Get firmware */ request_firmware(&fw, fw_name, &info->client->dev); if (!fw) { dev_err(&info->client->dev, "%s [ERROR] request_firmware\n", __func__); ret = FW_ERR_FILE_OPEN; goto error; } /* Restore firmware */ while (retry > 0) { ret = mip4_ts_restore_fw(info, fw->data, fw->size, sections); dev_err(&info->client->dev, "%s - mip4_ts_restore_fw[%d]\n", __func__, ret); if (ret >= FW_ERR_NONE) { break; } retry--; } if (retry <= 0) { dev_err(&info->client->dev, "%s [ERROR] mip4_ts_restore_fw failed\n", __func__); ret = FW_ERR_DOWNLOAD; } else { ret = FW_ERR_NONE; } release_firmware(fw); if (ret < FW_ERR_NONE) { goto error; } //mutex_unlock(&info->lock); dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return 0; error: //mutex_unlock(&info->lock); dev_err(&info->client->dev, "%s [ERROR]\n", __func__); return ret; } #endif /* * Update firmware from kernel built-in firmware file */ int mip4_ts_fw_update_from_kernel(struct mip4_ts_info *info) { const char *fw_name = FW_PATH_INTERNAL; const struct firmware *fw; int retry = 3; int ret = FW_ERR_NONE; dev_dbg(&info->client->dev, "%s [START]\n", __func__); /* Disable IRQ */ mutex_lock(&info->lock); disable_irq(info->client->irq); mip4_ts_clear_input(info); /* Get firmware */ request_firmware(&fw, fw_name, &info->client->dev); if (!fw) { dev_err(&info->client->dev, "%s [ERROR] request_firmware\n", __func__); ret = FW_ERR_FILE_OPEN; goto error; } /* Update firmware */ do { ret = mip4_ts_flash_fw(info, fw->data, fw->size, false, true); if (ret >= FW_ERR_NONE) { break; } } while (--retry); if (!retry) { dev_err(&info->client->dev, "%s [ERROR] mip4_ts_flash_fw failed\n", __func__); ret = FW_ERR_DOWNLOAD; } release_firmware(fw); /* Enable IRQ */ enable_irq(info->client->irq); mutex_unlock(&info->lock); if (ret < FW_ERR_NONE) { goto error; } dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); return 0; error: dev_err(&info->client->dev, "%s [ERROR]\n", __func__); return ret; } /* * Update firmware from external storage */ int mip4_ts_fw_update_from_storage(struct mip4_ts_info *info, char *path, bool force) { struct file *fp; mm_segment_t old_fs; size_t fw_size, nread; unsigned char *fw_data; int ret = FW_ERR_NONE; dev_dbg(&info->client->dev, "%s [START]\n", __func__); /* Disable IRQ */ mutex_lock(&info->lock); disable_irq(info->client->irq); mip4_ts_clear_input(info); /* Get firmware */ old_fs = get_fs(); set_fs(KERNEL_DS); fp = filp_open(path, O_RDONLY, S_IRUSR); if (IS_ERR(fp)) { dev_err(&info->client->dev, "%s [ERROR] file_open - path[%s]\n", __func__, path); ret = FW_ERR_FILE_OPEN; goto error; } fw_size = fp->f_path.dentry->d_inode->i_size; if (fw_size > 0) { /* Read firmware */ fw_data = kzalloc(fw_size, GFP_KERNEL); nread = vfs_read(fp, (char __user *)fw_data, fw_size, &fp->f_pos); dev_dbg(&info->client->dev, "%s - path[%s] size[%zu]\n", __func__, path, fw_size); if (nread != fw_size) { dev_err(&info->client->dev, "%s [ERROR] vfs_read - size[%zu] read[%zu]\n", __func__, fw_size, nread); ret = FW_ERR_FILE_READ; } else { /* Update firmware */ ret = mip4_ts_flash_fw(info, fw_data, fw_size, force, true); } kfree(fw_data); } else { dev_err(&info->client->dev, "%s [ERROR] fw_size[%zu]\n", __func__, fw_size); ret = FW_ERR_FILE_READ; } filp_close(fp, current->files); error: set_fs(old_fs); /* Enable IRQ */ enable_irq(info->client->irq); mutex_unlock(&info->lock); if (ret < FW_ERR_NONE) { dev_err(&info->client->dev, "%s [ERROR]\n", __func__); } else { dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); } return ret; } /* * Sysfs - firmware update */ static ssize_t mip4_ts_sys_fw_update(struct device *dev, struct device_attribute *attr, char *buf) { struct i2c_client *client = to_i2c_client(dev); struct mip4_ts_info *info = i2c_get_clientdata(client); int result = 0; u8 data[255]; int ret = 0; dev_dbg(&info->client->dev, "%s [START]\n", __func__); ret = mip4_ts_fw_update_from_kernel(info); switch (ret) { case FW_ERR_NONE: snprintf(data, sizeof(data), "F/W update success.\n"); break; case FW_ERR_UPTODATE: snprintf(data, sizeof(data), "F/W is already up-to-date.\n"); break; case FW_ERR_DOWNLOAD: snprintf(data, sizeof(data), "F/W update failed : Download error\n"); break; case FW_ERR_FILE_TYPE: snprintf(data, sizeof(data), "F/W update failed : Firmware type error\n"); break; case FW_ERR_FILE_OPEN: snprintf(data, sizeof(data), "F/W update failed : Firmware open error[%s]\n", FW_PATH_INTERNAL); break; case FW_ERR_FILE_READ: snprintf(data, sizeof(data), "F/W update failed : Firmware read error\n"); break; default: snprintf(data, sizeof(data), "F/W update failed.\n"); break; } /* Re-config driver */ mip4_ts_config(info); mip4_ts_config_input(info); dev_dbg(&info->client->dev, "%s [DONE]\n", __func__); result = snprintf(buf, 255, "%s\n", data); return result; } static DEVICE_ATTR(fw_update, S_IRUGO, mip4_ts_sys_fw_update, NULL); #endif /* CHIP_MODEL */ /* * Sysfs attr info */ static struct attribute *mip4_ts_attrs[] = { #if (CHIP_MODEL != CHIP_NONE) &dev_attr_fw_update.attr, #endif /* CHIP_MODEL */ NULL, }; /* * Sysfs attr group info */ static const struct attribute_group mip4_ts_attr_group = { .attrs = mip4_ts_attrs, }; /* * Initialize driver */ static int mip4_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct mip4_ts_info *info; struct input_dev *input_dev; int ret = 0; dev_dbg(&client->dev, "%s [START]\n", __func__); /* Check I2C functionality */ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { dev_err(&client->dev, "%s [ERROR] i2c_check_functionality\n", __func__); ret = -EIO; goto error_i2c; } /* Init info data */ info = devm_kzalloc(&client->dev, sizeof(struct mip4_ts_info), GFP_KERNEL); input_dev = devm_input_allocate_device(&client->dev); if (!info || !input_dev) { dev_err(&client->dev, "%s [ERROR]\n", __func__); ret = -ENOMEM; goto error_info; } info->client = client; info->input_dev = input_dev; info->init = true; info->power = -1; info->irq_enabled = false; info->fw_path_ext = devm_kstrdup(&client->dev, FW_PATH_EXTERNAL, GFP_KERNEL); mutex_init(&info->lock); init_completion(&info->startup_done); info->startup_init = false; info->debug_event = DEBUG_EVENT; /* Config platform */ ret = mip4_ts_config_platform(info); if (ret) { dev_err(&client->dev, "%s [ERROR] mip4_ts_config_platform\n", __func__); goto error_info; } /* Config input device */ //info->input_dev->name = "MELFAS_" CHIP_NAME "_Touchscreen"; info->input_dev->name = "sec_touchscreen"; //snprintf(info->phys, sizeof(info->phys), "%s/input0", dev_name(&client->dev)); snprintf(info->phys, sizeof(info->phys), "%s/input1", input_dev->name); info->input_dev->phys = info->phys; info->input_dev->id.bustype = BUS_I2C; info->input_dev->id.vendor = 0x13C5; info->input_dev->dev.parent = &client->dev; #if USE_INPUT_OPEN_CLOSE info->input_dev->open = mip4_ts_input_open; info->input_dev->close = mip4_ts_input_close; #endif /* USE_INPUT_OPEN_CLOSE */ /* Set info data */ input_set_drvdata(input_dev, info); i2c_set_clientdata(client, info); /* Config regulator */ mip4_ts_config_regulator(info); #if 0 mip4_ts_power_off(info, POWER_OFF_DELAY); #endif /* Firmware update */ #if USE_AUTO_FW_UPDATE mip4_ts_power_on(info, POWER_ON_DELAY); #if 1 ret = mip4_ts_fw_update_from_kernel(info); if (ret) { dev_err(&client->dev, "%s [ERROR] mip4_ts_fw_update_from_kernel\n", __func__); } #else ret = mip4_ts_fw_update_from_storage(info, FW_PATH_EXTERNAL, false); if (ret) { dev_err(&client->dev, "%s [ERROR] mip4_ts_fw_update_from_storage\n", __func__); } #endif mip4_ts_power_off(info, POWER_OFF_DELAY); #endif /* USE_AUTO_FW_UPDATE */ /* Set interrupt handler */ #if 1 //ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, mip4_ts_interrupt, IRQF_TRIGGER_LOW | IRQF_ONESHOT, MIP4_TS_DEVICE_NAME, info); ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, mip4_ts_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, MIP4_TS_DEVICE_NAME, info); //ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, mip4_ts_interrupt, 8200, MIP4_TS_DEVICE_NAME, info); //ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, mip4_ts_interrupt, 0, MIP4_TS_DEVICE_NAME, info); #else ret = 0; #endif if (ret) { dev_err(&client->dev, "%s [ERROR] request_threaded_irq\n", __func__); goto error_irq; } #if USE_WAKELOCK /* Wake-lock for low power mode */ wake_lock_init(&info->wake_lock, WAKE_LOCK_SUSPEND, "mip4_ts_wake_lock"); #endif /* USE_WAKELOCK */ disable_irq(info->client->irq); info->irq_enabled = false; info->startup_init = true; /* Enable device */ mip4_ts_enable(info); /* Config module */ ret = mip4_ts_config(info); if (ret) { dev_err(&client->dev, "%s [ERROR] mip4_ts_config\n", __func__); } /* Config input interface */ mip4_ts_config_input(info); /* Register input device */ ret = input_register_device(input_dev); if (ret) { dev_err(&client->dev, "%s [ERROR] input_register_device\n", __func__); ret = -EIO; goto error_device; } #if USE_FB_NOTIFY info->fb_notifier.notifier_call = mip4_ts_fb_notifier_callback; fb_register_client(&info->fb_notifier); #endif /* USE_FB_NOTIFY */ device_init_wakeup(&client->dev, true); #if USE_DEV /* Create dev node (optional) */ if (mip4_ts_dev_create(info)) { dev_err(&client->dev, "%s [ERROR] mip4_ts_dev_create\n", __func__); } info->class = class_create(THIS_MODULE, MIP4_TS_DEVICE_NAME); device_create(info->class, NULL, info->mip4_ts_dev, NULL, MIP4_TS_DEVICE_NAME); #endif /* USE_DEV */ #if USE_SYS /* Create sysfs for development functions (optional) */ if (mip4_ts_sysfs_create(info)) { dev_err(&client->dev, "%s [ERROR] mip4_ts_sysfs_create\n", __func__); } #endif /* USE_SYS */ #if 0//USE_CMD /* Create sysfs for command functions (optional) */ if (mip4_ts_sysfs_cmd_create(info)) { dev_err(&client->dev, "%s [ERROR] mip4_ts_sysfs_cmd_create\n", __func__); } #endif /* USE_CMD */ /* Create sysfs */ if (sysfs_create_group(&client->dev.kobj, &mip4_ts_attr_group)) { dev_err(&client->dev, "%s [ERROR] sysfs_create_group\n", __func__); } if (sysfs_create_link(NULL, &client->dev.kobj, MIP4_TS_DEVICE_NAME)) { dev_err(&client->dev, "%s [ERROR] sysfs_create_link\n", __func__); } dev_dbg(&client->dev, "%s [DONE]\n", __func__); dev_info(&client->dev, "MELFAS " CHIP_NAME " Touchscreen\n"); return 0; error_irq: free_irq(info->irq, info); error_device: input_unregister_device(info->input_dev); error_info: error_i2c: dev_dbg(&client->dev, "%s [ERROR]\n", __func__); dev_err(&client->dev, "MELFAS " CHIP_NAME " Touchscreen initialization failed.\n"); return ret; } /* * Remove driver */ static int mip4_ts_remove(struct i2c_client *client) { struct mip4_ts_info *info = i2c_get_clientdata(client); disable_irq(info->client->irq); free_irq(info->client->irq, info); #if 0// USE_CMD mip4_ts_sysfs_cmd_remove(info); #endif /* USE_CMD */ #if USE_SYS mip4_ts_sysfs_remove(info); #endif /* USE_SYS */ sysfs_remove_group(&info->client->dev.kobj, &mip4_ts_attr_group); sysfs_remove_link(NULL, MIP4_TS_DEVICE_NAME); #if USE_DEV device_destroy(info->class, info->mip4_ts_dev); class_destroy(info->class); #endif /* USE_DEV */ #if USE_FB_NOTIFY fb_unregister_client(&info->fb_notifier); #endif /* USE_FB_NOTIFY */ input_unregister_device(info->input_dev); info->input_dev = NULL; return 0; } /* * Shutdown */ static void mip4_ts_shutdown(struct i2c_client *client) { mip4_ts_remove(client); } #ifdef CONFIG_PM /* * Device suspend event handler */ int mip4_ts_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct mip4_ts_info *info = i2c_get_clientdata(client); dev_dbg(&client->dev, "%s [START]\n", __func__); mip4_ts_disable(info); dev_dbg(&client->dev, "%s [DONE]\n", __func__); return 0; } /* * Device resume event handler */ int mip4_ts_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct mip4_ts_info *info = i2c_get_clientdata(client); int ret = 0; dev_dbg(&client->dev, "%s [START]\n", __func__); mip4_ts_enable(info); dev_dbg(&client->dev, "%s [DONE]\n", __func__); return ret; } /* * PM info */ const struct dev_pm_ops mip4_ts_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(mip4_ts_suspend, mip4_ts_resume) }; #endif /* CONFIG_PM */ #ifdef CONFIG_OF /* * Devicetree match table */ static const struct of_device_id mip4_ts_of_match_table[] = { {.compatible = "melfas,mip4_ts",}, {}, }; MODULE_DEVICE_TABLE(of, mip4_ts_of_match_table); #endif /* CONFIG_OF */ #ifdef CONFIG_ACPI /* * ACPI match table */ static const struct acpi_device_id mip4_ts_acpi_match_table[] = { {ACPI_ID, 0}, {}, }; MODULE_DEVICE_TABLE(acpi, mip4_ts_acpi_match_table); #endif /* CONFIG_ACPI */ /* * I2C Device ID */ static const struct i2c_device_id mip4_ts_id[] = { {MIP4_TS_DEVICE_NAME, 0}, {}, }; MODULE_DEVICE_TABLE(i2c, mip4_ts_id); /* * I2C driver info */ static struct i2c_driver mip4_ts_driver = { .id_table = mip4_ts_id, .probe = mip4_ts_probe, .remove = mip4_ts_remove, .shutdown = mip4_ts_shutdown, .driver = { .name = MIP4_TS_DEVICE_NAME, .owner = THIS_MODULE, #ifdef CONFIG_OF .of_match_table = of_match_ptr(mip4_ts_of_match_table), #endif /* CONFIG_OF */ #ifdef CONFIG_ACPI .acpi_match_table = ACPI_PTR(mip4_ts_acpi_match_table), #endif /* CONFIG_ACPI */ #ifdef CONFIG_PM .pm = &mip4_ts_pm_ops, #endif /* CONFIG_PM */ }, }; module_i2c_driver(mip4_ts_driver); MODULE_DESCRIPTION("MELFAS MIP4 Touchscreen"); MODULE_VERSION("2018.12.04"); MODULE_AUTHOR("MELFAS Inc. "); MODULE_LICENSE("GPL");