diff --git a/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_class.c b/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_class.c index ab18816606d4..603c8c51702a 100644 --- a/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_class.c +++ b/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_class.c @@ -809,6 +809,29 @@ static int ts_mmi_default_pinctrl(struct device *parent, int on) return 0; } +static int ts_mmi_clip_event_handler(struct device *parent, + struct touch_event_data *tev, struct input_dev *input_dev) +{ + struct ts_mmi_dev *touch_cdev = ts_mmi_dev_to_cdev(parent); + bool inside; + + inside = (tev->x >= touch_cdev->clip.xUL) && (tev->x <= touch_cdev->clip.xBR) && + (tev->y >= touch_cdev->clip.yUL) && (tev->y <= touch_cdev->clip.yBR); + + if (inside == touch_cdev->clip.inversion) { + if (tev->type == TS_COORDINATE_ACTION_MOVE) { + /* cancel active touch when it falls off the clip area */ + input_mt_slot(input_dev, tev->id); + input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, false); + /* indicate cancelled touch to vendor driver */ + tev->type = TS_COORDINATE_ACTION_FORCE_LIFT; + } + tev->skip_report = true; + } + + return 0; +} + /** * ts_mmi_dev_register - register a new object of ts_mmi_dev class. * @parent: The device to register. @@ -955,6 +978,11 @@ int ts_mmi_dev_register(struct device *parent, } } + if (touch_cdev->pdata.clip_area_ctrl) { + /* export report touch event function to vendor */ + touch_cdev->mdata->exports.clip_touch_event = ts_mmi_clip_event_handler; + } + dev_info(DEV_TS, "Registered touchscreen device: %s.\n", class_fname); return 0; diff --git a/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_panel.c b/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_panel.c index 1bf855fa90e4..1b037dd32a1a 100644 --- a/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_panel.c +++ b/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_panel.c @@ -47,7 +47,7 @@ int ts_mmi_parse_dt(struct ts_mmi_dev *touch_cdev, { struct device_node *chosen; struct ts_mmi_dev_pdata *ppdata = &touch_cdev->pdata; - u32 coords[2]; + u32 coords[4]; dev_info(DEV_TS, "%s: Start parse touchscreen mmi device tree.\n", __func__); if (!of_property_read_string(of_node, "mmi,class-entry-name", &ppdata->class_entry_name)) @@ -172,6 +172,20 @@ int ts_mmi_parse_dt(struct ts_mmi_dev *touch_cdev, ppdata->support_liquid_detection = true; } + if (!of_property_read_u32_array(of_node, "mmi,clip-area", coords, 4)) { + ppdata->clip_area_ctrl = true; + touch_cdev->clip.xUL = coords[0]; + touch_cdev->clip.yUL = coords[1]; + touch_cdev->clip.xBR = coords[2]; + touch_cdev->clip.yBR = coords[3]; + if (of_property_read_bool(of_node, "mmi,clip-inversion")) + touch_cdev->clip.inversion = true; + dev_info(DEV_TS, "%s: clip %sarea: (%u,%u) (%u,%u)\n", __func__, + touch_cdev->clip.inversion ? "IN " : "OUT ", + touch_cdev->clip.xUL, touch_cdev->clip.yUL, + touch_cdev->clip.xBR, touch_cdev->clip.yBR); + } + 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 e41028daafe1..ccee2f10105e 100644 --- a/include/linux/touchscreen_mmi.h +++ b/include/linux/touchscreen_mmi.h @@ -246,7 +246,8 @@ enum touch_event_mode { TS_COORDINATE_ACTION_NONE = 0, TS_COORDINATE_ACTION_PRESS, TS_COORDINATE_ACTION_RELEASE, - TS_COORDINATE_ACTION_MOVE + TS_COORDINATE_ACTION_MOVE, + TS_COORDINATE_ACTION_FORCE_LIFT }; enum TS_FW_UPGRADE_MODE { @@ -270,6 +271,11 @@ struct gesture_event_data { }; }; +struct touch_clip_area { + unsigned xUL, yUL, xBR, yBR; + bool inversion; /* clip inside (when true) or outside otherwise */ +}; + /** * struct touchscreen_mmi_class_methods - export class methods to vendor * @@ -282,6 +288,7 @@ struct ts_mmi_class_methods { int (*get_class_fname)(struct device *dev , const char **fname); int (*get_supplier)(struct device *dev , const char **sname); int (*report_touch_event)(struct touch_event_data *tev, struct input_dev *input_dev); + int (*clip_touch_event)(struct device *dev, struct touch_event_data *tev, struct input_dev *input_dev); int (*report_liquid_detection_status)(struct device *parent, int status); struct kobject *kobj_notify; }; @@ -434,6 +441,7 @@ struct ts_mmi_dev_pdata { bool poison_slot_ctrl; bool active_region_ctrl; bool support_liquid_detection; + bool clip_area_ctrl; int max_x; int max_y; int fod_x; @@ -540,6 +548,7 @@ struct ts_mmi_dev { int update_baseline; struct attribute_group *extern_group; struct list_head node; + struct touch_clip_area clip; /* * vendor provided */