diff --git a/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_gesture.c b/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_gesture.c index 72f10dc9fdae..0178f6fed284 100644 --- a/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_gesture.c +++ b/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_gesture.c @@ -26,7 +26,12 @@ struct ts_mmi_sensor_platform_data { struct ts_mmi_dev *touch_cdev; }; +struct ts_mmi_touch_events_data { + struct ts_mmi_dev *touch_cdev; +}; + static struct ts_mmi_sensor_platform_data *sensor_pdata; +static struct ts_mmi_touch_events_data *events_data; static int ts_mmi_gesture_handler(struct gesture_event_data *gev) { @@ -62,6 +67,9 @@ static int ts_mmi_gesture_handler(struct gesture_event_data *gev) static int ts_mmi_touch_event_handler(struct touch_event_data *tev) { + struct ts_mmi_dev *touch_cdev = events_data->touch_cdev; + int ret = 0; + switch (tev->type) { case TS_COORDINATE_ACTION_PRESS: #if defined(CONFIG_TOUCHCLASS_MMI_DEBUG_INFO) @@ -74,6 +82,13 @@ static int ts_mmi_touch_event_handler(struct touch_event_data *tev) #if defined(CONFIG_TOUCHCLASS_MMI_DEBUG_INFO) pr_info("%s: [R]Finger %d: UP", __func__, tev->id); #endif + + if (touch_cdev->pdata.fps_detection) { + if (touch_cdev->delay_baseline_update) { + TRY_TO_CALL(update_baseline, TS_MMI_UPDATE_BASELINE_ON); + touch_cdev->delay_baseline_update = false; + } + } break; default: @@ -147,9 +162,16 @@ int ts_mmi_gesture_init(struct ts_mmi_dev *touch_cdev) sensor_pdata = devm_kzalloc(&sensor_input_dev->dev, sizeof(struct ts_mmi_sensor_platform_data), GFP_KERNEL); if (!sensor_pdata) { + dev_err(DEV_TS, "%s: Failed to allocate memory", __func__); + goto free_sensor_input_dev; + } + events_data = devm_kzalloc(DEV_TS, + sizeof(struct ts_mmi_touch_events_data), GFP_KERNEL); + if (!events_data) { dev_err(DEV_TS, "%s: Failed to allocate memory", __func__); goto free_sensor_pdata; } + events_data->touch_cdev = touch_cdev; __set_bit(EV_KEY, sensor_input_dev->evbit); __set_bit(KEY_F1, sensor_input_dev->keybit); @@ -166,7 +188,7 @@ int ts_mmi_gesture_init(struct ts_mmi_dev *touch_cdev) err = input_register_device(sensor_input_dev); if (err) { dev_err(DEV_TS, "%s: Unable to register device, err=%d", __func__, err); - goto free_sensor_input_dev; + goto free_touch_events_data; } sensor_pdata->ps_cdev = sensors_touch_cdev; @@ -187,10 +209,12 @@ int ts_mmi_gesture_init(struct ts_mmi_dev *touch_cdev) unregister_sensor_input_device: input_unregister_device(sensor_input_dev); -free_sensor_input_dev: - input_free_device(sensor_input_dev); +free_touch_events_data: + devm_kfree(DEV_TS, events_data); free_sensor_pdata: devm_kfree(&sensor_input_dev->dev, sensor_pdata); +free_sensor_input_dev: + input_free_device(sensor_input_dev); exit: return 1; } @@ -200,6 +224,8 @@ int ts_mmi_gesture_remove(struct ts_mmi_dev *touch_cdev) sensors_classdev_unregister(&sensor_pdata->ps_cdev); input_unregister_device(sensor_pdata->input_sensor_dev); devm_kfree(&sensor_pdata->input_sensor_dev->dev, sensor_pdata); + devm_kfree(DEV_TS, events_data); + input_free_device(sensor_pdata->input_sensor_dev); sensor_pdata = NULL; return 0; diff --git a/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_notif.c b/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_notif.c index c9f4bc32cf09..1a69f679c2b5 100644 --- a/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_notif.c +++ b/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_notif.c @@ -17,6 +17,7 @@ #include #include #include +#include #if defined(CONFIG_DRM_DYNAMIC_REFRESH_RATE) extern struct blocking_notifier_head dsi_freq_head; @@ -44,7 +45,8 @@ extern struct blocking_notifier_head dsi_freq_head; enum ts_mmi_work { TS_MMI_DO_RESUME, TS_MMI_DO_PS, - TS_MMI_DO_REFRESH_RATE + TS_MMI_DO_REFRESH_RATE, + TS_MMI_DO_FPS, }; static int ts_mmi_panel_off(struct ts_mmi_dev *touch_cdev) { @@ -182,6 +184,21 @@ static void ts_mmi_queued_resume(struct ts_mmi_dev *touch_cdev) TRY_TO_CALL(pre_resume); + /* touch IC baseline update always done when IC resume. + * So touchscreen class need let vendor driver know baseline update work need to be done + * or not before vendor resume is called. + */ + if (touch_cdev->pdata.fps_detection) { + if (touch_cdev->fps_state) { + TRY_TO_CALL(update_baseline, TS_MMI_UPDATE_BASELINE_OFF); + touch_cdev->delay_baseline_update = true; + } + if (!touch_cdev->fps_state) { + TRY_TO_CALL(update_baseline, TS_MMI_UPDATE_BASELINE_ON); + touch_cdev->delay_baseline_update = false; + } + } + if (NEED_TO_SET_POWER) { /* power turn on in PANEL_EVENT_PRE_DISPLAY_ON. * IC need some time to boot up. @@ -246,6 +263,17 @@ static void ts_mmi_worker_func(struct work_struct *w) case TS_MMI_DO_REFRESH_RATE: TRY_TO_CALL(refresh_rate, (int)touch_cdev->refresh_rate); break; + case TS_MMI_DO_FPS: + if (touch_cdev->fps_state) {/* on */ + TRY_TO_CALL(update_baseline, TS_MMI_UPDATE_BASELINE_OFF); + touch_cdev->delay_baseline_update = true; + } else { /* off */ + if (touch_cdev->delay_baseline_update) { + TRY_TO_CALL(update_baseline, TS_MMI_UPDATE_BASELINE_ON); + touch_cdev->delay_baseline_update = false; + } + } + break; default: dev_dbg(DEV_MMI, "%s: unknown command %d\n", __func__, cmd); } @@ -324,6 +352,57 @@ static int ts_mmi_charger_cb(struct notifier_block *self, return 0; } +static int ts_mmi_fps_cb(struct notifier_block *self, + unsigned long event, void *p) +{ + int fps_state = *(int *)p; + struct ts_mmi_dev *touch_cdev = container_of( + self, struct ts_mmi_dev, fps_notif); + + if (touch_cdev && event == 0xBEEF && fps_state != touch_cdev->fps_state) { + touch_cdev->fps_state = fps_state; + dev_info(DEV_MMI, "FPS: state is %s\n", touch_cdev->fps_state ? "ON" : "OFF"); + if (is_touch_active) { + kfifo_put(&touch_cdev->cmd_pipe, TS_MMI_DO_FPS); + schedule_delayed_work(&touch_cdev->work, 0); + } + } + + return 0; +} + +static int ts_mmi_fps_notifier_register(struct ts_mmi_dev *touch_cdev, bool enable) { + int (*register_link)(struct notifier_block *nb, unsigned long stype, bool report); + int (*unregister_link)(struct notifier_block *nb, unsigned long stype); + int ret; + + if (enable) { + register_link = symbol_get(FPS_register_notifier); + if (register_link) { + touch_cdev->fps_notif.notifier_call = ts_mmi_fps_cb; + ret = register_link(&touch_cdev->fps_notif, 0xBEEF, false); + symbol_put(FPS_register_notifier); + if (ret < 0) { + dev_err(DEV_TS, + "Failed to register fps_notifier: %d\n", ret); + return ret; + } + touch_cdev->is_fps_registered = true; + dev_info(DEV_TS, "Register fps_notifier OK\n"); + } else + dev_err(DEV_TS, "no FPS_register_notifier exported.\n"); + } else if (touch_cdev->is_fps_registered) { + unregister_link = symbol_get(FPS_unregister_notifier); + if (unregister_link) + unregister_link(&touch_cdev->fps_notif, 0xBEEF); + else + dev_err(DEV_TS, "no FPS_unregister_notifier exported.\n"); + touch_cdev->is_fps_registered = false; + } + + return 0; +} + int ts_mmi_notifiers_register(struct ts_mmi_dev *touch_cdev) { int ret = 0; @@ -366,6 +445,13 @@ int ts_mmi_notifiers_register(struct ts_mmi_dev *touch_cdev) goto FREQ_NOTIF_REGISTER_FAILED; } + if (touch_cdev->pdata.fps_detection) { + ret = ts_mmi_fps_notifier_register(touch_cdev, true); + if (ret < 0) + dev_err(DEV_TS, + "Failed to register fps_notifier: %d\n", ret); + } + dev_info(DEV_TS, "%s: Notifiers init OK.\n", __func__); return 0; @@ -386,6 +472,9 @@ void ts_mmi_notifiers_unregister(struct ts_mmi_dev *touch_cdev) return; } + if (touch_cdev->pdata.fps_detection) + ts_mmi_fps_notifier_register(touch_cdev, false); + if (touch_cdev->pdata.update_refresh_rate) unregister_dynamic_refresh_rate_notifier(&touch_cdev->freq_nb); diff --git a/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_panel.c b/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_panel.c index 1eb814416aa2..5689dad3be82 100644 --- a/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_panel.c +++ b/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_panel.c @@ -113,6 +113,11 @@ int ts_mmi_parse_dt(struct ts_mmi_dev *touch_cdev, ppdata->hold_grip_ctrl = true; } + if (of_property_read_bool(of_node, "mmi,fps_detection")) { + dev_info(DEV_TS, "%s: using fps detection\n", __func__); + ppdata->fps_detection = true; + } + chosen = of_find_node_by_name(NULL, "chosen"); if (chosen) { struct device_node *child; diff --git a/include/linux/touchscreen_mmi.h b/include/linux/touchscreen_mmi.h index f578092372de..5b5767d62bfa 100644 --- a/include/linux/touchscreen_mmi.h +++ b/include/linux/touchscreen_mmi.h @@ -229,6 +229,7 @@ enum ts_mmi_pm_mode { struct ts_mmi_dev_pdata { bool power_off_suspend; + bool fps_detection; bool usb_detection; bool update_refresh_rate; bool gestures_enabled; @@ -286,6 +287,12 @@ struct ts_mmi_dev { struct work_struct ps_notify_work; struct notifier_block ps_notif; bool ps_is_present; + + struct notifier_block fps_notif; + bool is_fps_registered; /* FPS notif registration might be delayed */ + bool fps_state; + bool delay_baseline_update; + /* * sys entey variable */