Cypfg: dlkm: Improve gcore_mmi driver

- Request irq change to thread.
- Resume will use thread instead of queue.
- Fixed irq panic issue.

Change-Id: I9e54944fc276d8554db2b5c23042693923f2e5cc
Signed-off-by: wengjun1 <wengjun1@motorola.com>
Reviewed-on: https://gerrit.mot.com/1990930
SLTApproved: Slta Waiver
SME-Granted: SME Approvals Granted
Tested-by: Jira Key
Reviewed-by: Huosheng Liao <liaohs@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
wengjun1 2021-06-24 18:41:28 +08:00 • committed by Jun Weng
commit d4b40823fe
7 changed files with 239 additions and 63 deletions

10
drivers/input/touchscreen/gcore_mmi/gcore_drv_common.h Normal file → Executable file
View file

@ -250,7 +250,6 @@ static const struct of_device_id tpd_of_match[] = {
#define GESTURE_KEY KEY_POWER
#endif
#ifdef CONFIG_ENABLE_FW_RAWDATA
enum FW_MODE {
DEMO,
@ -277,7 +276,7 @@ struct gcore_dev {
struct spi_device *bus_device;
#endif
unsigned int touch_irq;
int touch_irq;
spinlock_t irq_flag_lock;
int irq_flag;
int tpd_flag;
@ -396,5 +395,12 @@ extern int gcore_ts_drm_notifier_callback(struct notifier_block *self,
unsigned long event, void *data);
#endif
extern int gcore_start_mp_test(void);
#define RESUME_USES_WORKQ 1
#if RESUME_USES_WORKQ
extern void gcore_resume_wq_init(void);
#endif
#endif /* GCORE_TPD_COMMON_H_ */

View file

@ -1905,6 +1905,13 @@ static int fwu_event_handler(void *p)
wait_event_interruptible(gdev->wait, fw_update_fn.event_flag == true);
fw_update_fn.event_flag = false;
if (mutex_is_locked(&gdev->transfer_lock)) {
GTP_DEBUG("fw event is locked, ignore");
continue;
}
mutex_lock(&gdev->transfer_lock);
switch (gdev->fw_event) {
case FW_UPDATE:
#ifdef CONFIG_GCORE_AUTO_UPDATE_FW_HOSTDOWNLOAD
@ -1922,7 +1929,7 @@ static int fwu_event_handler(void *p)
break;
}
gdev_fwu->irq_enable(gdev_fwu);
mutex_unlock(&gdev->transfer_lock);
} while (!kthread_should_stop());

View file

@ -254,6 +254,17 @@ long gcore_app_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
break;
case IOC_APP_START_MP_TEST:
GTP_DEBUG("App ioctl start mp test");
if (gcore_start_mp_test()) {
GTP_ERROR("App ioctl mp test fail!");
return -1;
}
break;
default:
GTP_ERROR("ioctl unknow cmd!");
return -ENOTTY;

80
drivers/input/touchscreen/gcore_mmi/gcore_drv_main.c Normal file → Executable file
View file

@ -629,41 +629,30 @@ s32 gcore_touch_event_handler(struct gcore_dev *gdev)
return 0;
}
static int tpd_event_handler(void *p)
static irqreturn_t tpd_event_handler(int irq, void *dev_id)
{
struct gcore_dev *gdev = (struct gcore_dev *)p;
struct sched_param param = {.sched_priority = 4};
struct gcore_dev *gdev = (struct gcore_dev *)dev_id;
sched_setscheduler(current, SCHED_RR, &param);
do {
set_current_state(TASK_INTERRUPTIBLE);
if (mutex_is_locked(&gdev->transfer_lock)) {
GTP_DEBUG("touch is locked, ignore");
return IRQ_HANDLED;
}
wait_event_interruptible(gdev->wait, gdev->tpd_flag != 0);
gdev->tpd_flag = 0;
mutex_lock(&gdev->transfer_lock);
/* don't reset before "if (tpd_halt..." */
set_current_state(TASK_RUNNING);
if (gcore_touch_event_handler(gdev)) {
GTP_ERROR("touch event handler error.");
}
mutex_lock(&gdev->transfer_lock);
/* don't reset before "if (tpd_halt..." */
mutex_unlock(&gdev->transfer_lock);
if (gcore_touch_event_handler(gdev)) {
GTP_ERROR("touch event handler error.");
}
gcore_irq_enable(gdev);
mutex_unlock(&gdev->transfer_lock);
} while (!kthread_should_stop());
return 0;
return IRQ_HANDLED;
}
static irqreturn_t tpd_eint_interrupt_handler(unsigned irq, void *p)
static irqreturn_t tpd_eint_interrupt_handler(int irq, void *dev_id)
{
struct gcore_dev *gdev = (struct gcore_dev *)p;
unsigned long flags;
struct gcore_dev *gdev = (struct gcore_dev *)dev_id;
struct gcore_exp_fn *exp_fn = NULL;
struct gcore_exp_fn *exp_fn_temp = NULL;
u8 found = 0;
@ -680,22 +669,12 @@ static irqreturn_t tpd_eint_interrupt_handler(unsigned irq, void *p)
if (!found) {
gdev->tpd_flag = 1;
}
spin_lock_irqsave(&gdev->irq_flag_lock, flags);
if (gdev->irq_flag == 0) {
spin_unlock_irqrestore(&gdev->irq_flag_lock, flags);
return IRQ_WAKE_THREAD;
} else {
wake_up_interruptible(&gdev->wait);
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 */
gdev->irq_flag = 0;
spin_unlock_irqrestore(&gdev->irq_flag_lock, flags);
disable_irq_nosync(gdev->touch_irq);
/*GTP_DEBUG("disable irq_flag=%d",g_touch.irq_flag);*/
wake_up_interruptible(&gdev->wait);
return IRQ_HANDLED;
}
static int tpd_irq_registration(struct gcore_dev *gdev)
@ -741,8 +720,10 @@ static int tpd_irq_registration(struct gcore_dev *gdev)
#endif
ret = request_irq(gdev->touch_irq, (irq_handler_t) tpd_eint_interrupt_handler,
IRQF_TRIGGER_RISING, "TOUCH_PANEL-eint", gdev);
ret = devm_request_threaded_irq(&gdev->bus_device->dev, gdev->touch_irq,
tpd_eint_interrupt_handler,
tpd_event_handler,
IRQF_TRIGGER_RISING | IRQF_ONESHOT, "TOUCH_PANEL-eint", gdev);
if (ret > 0) {
ret = -1;
GTP_ERROR("tpd request_irq IRQ LINE NOT AVAILABLE!.");
@ -873,12 +854,6 @@ void gcore_deinit(struct gcore_dev *gdev)
}
}
if (gdev->touch_irq) {
free_irq(gdev->touch_irq, gdev);
}
kthread_stop(gdev->thread);
destroy_workqueue(gdev->fwu_workqueue);
if (gdev->touch_data) {
@ -898,7 +873,6 @@ void gcore_deinit(struct gcore_dev *gdev)
int gcore_touch_probe(struct gcore_dev *gdev)
{
s32 err = 0;
#if 0
struct gcore_exp_fn *exp_fn = NULL;
struct gcore_exp_fn *exp_fn_temp = NULL;
@ -914,11 +888,6 @@ int gcore_touch_probe(struct gcore_dev *gdev)
GTP_ERROR("gcore init fail!");
}
gdev->thread = kthread_run(tpd_event_handler, gdev, GTP_DRIVER_NAME);
if (IS_ERR(gdev->thread)) {
err = PTR_ERR(gdev->thread);
GTP_DEBUG(GTP_DRIVER_NAME " failed to create kernel thread: %d\n", err);
}
#ifdef CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM
tpd_gpio_as_int(GTP_INT_PORT);
@ -970,6 +939,11 @@ int gcore_touch_probe(struct gcore_dev *gdev)
GTP_ERROR("register notifier failed!");
}
#endif
#if RESUME_USES_WORKQ
gcore_resume_wq_init();
#endif
#endif
return 0;

View file

@ -193,6 +193,92 @@ int gcore_parse_mp_test_dt(struct gcore_mp_data *mp_data)
return 0;
}
#define MP_TEST_INI "/sdcard/gcore_mp_test.ini"
static u8 *read_line(u8 *buf, int buf_len, struct file *fp)
{
int ret;
int i = 0;
mm_segment_t fs;
fs = get_fs();
set_fs(KERNEL_DS);
ret = fp->f_op->read(fp, buf, buf_len, &(fp->f_pos));
set_fs(fs);
if (ret <= 0)
return NULL;
while (buf[i] != '\n' && i < ret) {
i++;
}
if (i < ret) {
fp->f_pos += i-ret;
}
if (i < buf_len) {
buf[i] = 0;
}
return buf;
}
int gcore_parse_mp_test_ini(struct gcore_mp_data *mp_data)
{
struct file *f = NULL;
u8 *buff = NULL;
int buff_len = 20;
buff = kzalloc(buff_len, GFP_KERNEL);
if (!buff) {
GTP_ERROR("file mem alloc fail!");
return -1;
}
f = filp_open(MP_TEST_INI, O_RDONLY, 644);
if (!f) {
GTP_ERROR("open mp test ini file fail!");
return -1;
}
buff = read_line(buff, buff_len, f);
GTP_DEBUG("ini read line %s", buff);
buff = read_line(buff, buff_len, f);
GTP_DEBUG("ini read line %s", buff);
sscanf(buff, "open_cb=%d", &mp_data->open_cb);
GTP_DEBUG("read open cb:%d", mp_data->open_cb);
buff = read_line(buff, buff_len, f);
GTP_DEBUG("ini read line %s", buff);
sscanf(buff, "open_min=%d", &mp_data->open_min);
GTP_DEBUG("read open min:%d", mp_data->open_min);
buff = read_line(buff, buff_len, f);
GTP_DEBUG("ini read line %s", buff);
sscanf(buff, "short_cb=%d", &mp_data->short_cb);
GTP_DEBUG("read short cb:%d", mp_data->short_cb);
buff = read_line(buff, buff_len, f);
GTP_DEBUG("ini read line %s", buff);
sscanf(buff, "short_min=%d", &mp_data->short_min);
GTP_DEBUG("read short min:%d", mp_data->short_min);
if (f != NULL) {
filp_close(f, NULL);
}
kfree(buff);
mp_data->test_chip_id = true;
mp_data->test_int_pin = true;
mp_data->test_open = true;
mp_data->test_short = true;
return 0;
}
int gcore_mp_test_int_pin(struct gcore_mp_data *mp_data)
{
u8 read_buf[4] = { 0 };
@ -442,6 +528,13 @@ static int mp_test_event_handler(void *p)
wait_event_interruptible(gdev->wait, mp_test_fn.event_flag == true);
mp_test_fn.event_flag = false;
if (mutex_is_locked(&gdev->transfer_lock)) {
GTP_DEBUG("fw event is locked, ignore");
continue;
}
mutex_lock(&gdev->transfer_lock);
switch (gdev->fw_event) {
case FW_READ_OPEN:
gcore_mp_test_item_open_reply(gdev->firmware, gdev->fw_xfer);
@ -455,7 +548,7 @@ static int mp_test_event_handler(void *p)
break;
}
gdev->irq_enable(gdev);
mutex_unlock(&gdev->transfer_lock);
} while (!kthread_should_stop());
@ -666,6 +759,65 @@ int gcore_save_mp_data_to_file(struct gcore_mp_data *mp_data)
return 0;
}
int gcore_start_mp_test(void)
{
struct gcore_mp_data *mp_data = g_mp_data;
int test_result = 0;
GTP_DEBUG("gcore start mp test.");
gcore_parse_mp_test_ini(mp_data);
gcore_alloc_mp_test_mem(mp_data);
if (mp_data->test_int_pin) {
mp_data->int_pin_test_result = gcore_mp_test_int_pin(mp_data);
}
msleep(1);
if (mp_data->test_chip_id) {
mp_data->chip_id_test_result = gcore_mp_test_chip_id(mp_data);
}
msleep(1);
if (mp_data->test_open || mp_data->test_short) {
GTP_DEBUG("mp test begin to updata mp bin");
#ifdef CONFIG_GCORE_AUTO_UPDATE_FW_HOSTDOWNLOAD
if (gcore_auto_update_hostdownload_proc(gcore_mp_FW)) {
GTP_ERROR("mp bin update hostdownload proc fail");
}
// gcore_request_firmware_update_work(NULL);
#endif
else {
msleep(1);
if (mp_data->test_open) {
mp_data->open_test_result = gcore_mp_test_item_open(mp_data);
}
msleep(1);
if (mp_data->test_short) {
mp_data->short_test_result = gcore_mp_test_item_short(mp_data);
}
}
}
gcore_save_mp_data_to_file(mp_data);
test_result = (mp_data->int_pin_test_result || mp_data->chip_id_test_result \
|| mp_data->open_test_result || mp_data->short_test_result) ? -1 : 0;
GTP_DEBUG("start mp test result:%d", test_result);
return test_result;
}
static int32_t gcore_mp_test_open(struct inode *inode, struct file *file)
{
struct gcore_mp_data *mp_data = PDE_DATA(inode);

27
drivers/input/touchscreen/gcore_mmi/gcore_drv_qcom.c Normal file → Executable file
View file

@ -23,6 +23,27 @@
#include <drm/drm_panel.h>
#endif
#if RESUME_USES_WORKQ
static struct workqueue_struct *resume_by_ddi_wq;
static struct work_struct resume_by_ddi_work;
void gcore_resume_by_ddi_work(struct work_struct *work)
{
gcore_request_firmware_update_work(NULL);
gcore_touch_release_all_point(fn_data.gdev->input_device);
fn_data.gdev->tp_suspend = false;
}
void gcore_resume_wq_init(void)
{
resume_by_ddi_wq = create_singlethread_workqueue("resume_by_ddi_wq");
WARN_ON(!resume_by_ddi_wq);
INIT_WORK(&resume_by_ddi_work, gcore_resume_by_ddi_work);
}
#endif
#if defined(CONFIG_ENABLE_GESTURE_WAKEUP) && defined(CONFIG_GESTURE_SPECIAL_INT)
int gcore_enable_irq_wake(struct gcore_dev *gdev)
@ -115,6 +136,7 @@ void gcore_resume(void)
GTP_DEBUG("enter gcore resume");
#if !RESUME_USES_WORKQ
#if defined(CONFIG_ENABLE_GESTURE_WAKEUP) && defined(CONFIG_GESTURE_SPECIAL_INT)
struct gcore_dev *gdev = fn_data.gdev;
if (gdev->gesture_wakeup_en) {
@ -137,10 +159,13 @@ void gcore_resume(void)
gcore_touch_release_all_point(fn_data.gdev->input_device);
fn_data.gdev->tp_suspend = false;
#else
queue_work(resume_by_ddi_wq, &(resume_by_ddi_work));
GTP_DEBUG("TP resume work queued.");
#endif
}
#ifdef CONFIG_DRM
int gcore_ts_drm_notifier_callback(struct notifier_block *self,
unsigned long event, void *data)

View file

@ -27,7 +27,7 @@ struct reg_msg {
};
#define GALAXYCORE_MAGIC_NUMBER 'G'
#define GALAXYCORE_MAX_NR 11
#define GALAXYCORE_MAX_NR 12
#define IOC_APP_READ_FW_VERSION _IOR(GALAXYCORE_MAGIC_NUMBER, 0, char)
#define IOC_APP_UPDATE_FW _IOW(GALAXYCORE_MAGIC_NUMBER, 1, char)
#define IOC_APP_DEMO _IO(GALAXYCORE_MAGIC_NUMBER, 2)
@ -35,12 +35,13 @@ struct reg_msg {
#define IOC_APP_READ_REG _IOR(GALAXYCORE_MAGIC_NUMBER, 4, struct reg_msg)
#define IOC_APP_WRITE_REG _IOW(GALAXYCORE_MAGIC_NUMBER, 5, struct reg_msg)
#define IOC_APP_GET_RAWDATA_RES _IOR(GALAXYCORE_MAGIC_NUMBER, 6, char)
#define IOC_APP_START_MP_TEST _IO(GALAXYCORE_MAGIC_NUMBER, 7)
/* Tool */
#define IOC_DEBUG_TIME_RST0 _IO(GALAXYCORE_MAGIC_NUMBER, 7)
#define IOC_DEBUG_TIME_RST1 _IO(GALAXYCORE_MAGIC_NUMBER, 8)
#define IOC_TOOL_MODE _IOW(GALAXYCORE_MAGIC_NUMBER, 9, int)
#define IOC_TOOL_IDM_OPERATION _IOW(GALAXYCORE_MAGIC_NUMBER, 10, int)
#define IOC_DEBUG_TIME_RST0 _IO(GALAXYCORE_MAGIC_NUMBER, 8)
#define IOC_DEBUG_TIME_RST1 _IO(GALAXYCORE_MAGIC_NUMBER, 9)
#define IOC_TOOL_MODE _IOW(GALAXYCORE_MAGIC_NUMBER, 10, int)
#define IOC_TOOL_IDM_OPERATION _IOW(GALAXYCORE_MAGIC_NUMBER, 11, int)
#endif /* _GCORE_IOCTL_H_ */