From ac34679e2d6dcd6563eddee77eaf067df473f7f4 Mon Sep 17 00:00:00 2001 From: Shantanu Jain Date: Mon, 11 Jan 2016 16:13:30 +0530 Subject: [PATCH] input: misc: add support for scaling X and Y touch co-ordinates In certain situations, due to resolution mismatch, we may need to scale up/down the X and Y co-ordinates returned by the touch controller. Add support for the same where we scale up/down the X and Y touch co-ordinates returned from the touch controller before sending it to android. In such cases, we also need to ensure that the display resolution matches the touch resolution. Add support for that as well. Change-Id: Ia2dabf480478e26db1e1f0d92ca9ba5a252f18eb Signed-off-by: Shantanu Jain --- .../devicetree/bindings/input/hbtp-input.txt | 16 +++ drivers/input/misc/hbtp_input.c | 124 +++++++++++++++++- 2 files changed, 138 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/input/hbtp-input.txt b/Documentation/devicetree/bindings/input/hbtp-input.txt index da7057b25089..f422d75e037e 100644 --- a/Documentation/devicetree/bindings/input/hbtp-input.txt +++ b/Documentation/devicetree/bindings/input/hbtp-input.txt @@ -18,6 +18,16 @@ Optional properties: - qcom,dig-load : Digital supply load in uA - qcom,dig-vtg-min : Digital supply minimum voltage in uV - qcom,dig-vtg-max : Digital supply maximum voltage in uV + - qcom,display-resolution : Display resolution - maxX, maxY + - qcom,use-scale : boolean, enables the scaling for touch coordinates + +Optional properties if qcom,use-scale DT property is defined: + - qcom,def-maxx : default X-resolution of the touch panel. + - qcom,def-maxy : default Y-resolution of the touch panel. + (Above two properties should be defined in pairs only) + - qcom,des-maxx : desired X-resolution of the touch panel. + - qcom,des-maxy : desired Y-resolution of the touch panel. + (Above two properties should be defined in pairs only) Example: &soc { @@ -31,5 +41,11 @@ Example: qcom,dig-load = <15000>; qcom,dig-vtg-min = <1800000>; qcom,dig-vtg-max = <1800000>; + qcom,display-resolution = <719 1279>; + qcom,use-scale; + qcom,default-max-x = <1080>; + qcom,default-max-y = <1920>; + qcom,desired-max-x = <720>; + qcom,desired-max-y = <1280>; }; }; diff --git a/drivers/input/misc/hbtp_input.c b/drivers/input/misc/hbtp_input.c index 7a701647a612..2fe56ff541a3 100644 --- a/drivers/input/misc/hbtp_input.c +++ b/drivers/input/misc/hbtp_input.c @@ -1,5 +1,5 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -30,6 +30,7 @@ #endif #define HBTP_INPUT_NAME "hbtp_input" +#define DISP_COORDS_SIZE 2 struct hbtp_data { struct platform_device *pdev; @@ -48,6 +49,14 @@ struct hbtp_data { int dig_load_ua; int dig_vtg_min_uv; int dig_vtg_max_uv; + int disp_maxx; /* Display Max X */ + int disp_maxy; /* Display Max Y */ + int def_maxx; /* Default Max X */ + int def_maxy; /* Default Max Y */ + int des_maxx; /* Desired Max X */ + int des_maxy; /* Desired Max Y */ + bool use_scaling; + bool override_disp_coords; bool manage_afe_power_ana; bool manage_power_dig; }; @@ -140,6 +149,13 @@ static int hbtp_input_create_input_dev(struct hbtp_input_absinfo *absinfo) abs->minimum, abs->maximum, 0, 0); } + if (hbtp->override_disp_coords) { + input_set_abs_params(input_dev, ABS_MT_POSITION_X, + 0, hbtp->disp_maxx, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, + 0, hbtp->disp_maxy, 0, 0); + } + error = input_register_device(input_dev); if (error) { pr_err("%s: input_register_device failed\n", __func__); @@ -184,9 +200,29 @@ static int hbtp_input_report_events(struct hbtp_data *hbtp_data, input_report_abs(hbtp_data->input_dev, ABS_MT_PRESSURE, tch->pressure); + /* + * Scale up/down the X-coordinate as per + * DT property + */ + if (hbtp_data->use_scaling && + hbtp_data->def_maxx > 0 && + hbtp_data->des_maxx > 0) + tch->x = (tch->x * hbtp_data->des_maxx) + / hbtp_data->def_maxx; + input_report_abs(hbtp_data->input_dev, ABS_MT_POSITION_X, tch->x); + /* + * Scale up/down the Y-coordinate as per + * DT property + */ + if (hbtp_data->use_scaling && + hbtp_data->def_maxy > 0 && + hbtp_data->des_maxy > 0) + tch->y = (tch->y * hbtp_data->des_maxy) + / hbtp_data->def_maxy; + input_report_abs(hbtp_data->input_dev, ABS_MT_POSITION_Y, tch->y); @@ -416,9 +452,11 @@ MODULE_ALIAS("devname:" HBTP_INPUT_NAME); #ifdef CONFIG_OF static int hbtp_parse_dt(struct device *dev) { - int rc; + int rc, size; struct device_node *np = dev->of_node; + struct property *prop; u32 temp_val; + u32 disp_reso[DISP_COORDS_SIZE]; if (of_find_property(np, "vcc_ana-supply", NULL)) hbtp->manage_afe_power_ana = true; @@ -476,6 +514,88 @@ static int hbtp_parse_dt(struct device *dev) } } + prop = of_find_property(np, "qcom,display-resolution", NULL); + if (prop != NULL) { + if (!prop->value) + return -ENODATA; + + size = prop->length / sizeof(u32); + if (size != DISP_COORDS_SIZE) { + dev_err(dev, "invalid qcom,display-resolution DT property\n"); + return -EINVAL; + } + + rc = of_property_read_u32_array(np, "qcom,display-resolution", + disp_reso, size); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read DT property qcom,display-resolution\n"); + return rc; + } + + hbtp->disp_maxx = disp_reso[0]; + hbtp->disp_maxy = disp_reso[1]; + + hbtp->override_disp_coords = true; + } + + hbtp->use_scaling = of_property_read_bool(np, "qcom,use-scale"); + if (hbtp->use_scaling) { + rc = of_property_read_u32(np, "qcom,default-max-x", &temp_val); + if (!rc) { + hbtp->def_maxx = (int) temp_val; + } else if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read default max x\n"); + return rc; + } + + rc = of_property_read_u32(np, "qcom,desired-max-x", &temp_val); + if (!rc) { + hbtp->des_maxx = (int) temp_val; + } else if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read desired max x\n"); + return rc; + } + + /* + * Either both DT properties i.e. Default max X and + * Desired max X should be defined simultaneously, or none + * of them should be defined. + */ + if ((hbtp->def_maxx == 0 && hbtp->des_maxx != 0) || + (hbtp->def_maxx != 0 && hbtp->des_maxx == 0)) { + dev_err(dev, "default or desired max-X properties are incorrect\n"); + return -EINVAL; + } + + rc = of_property_read_u32(np, "qcom,default-max-y", &temp_val); + if (!rc) { + hbtp->def_maxy = (int) temp_val; + } else if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read default max y\n"); + return rc; + } + + rc = of_property_read_u32(np, "qcom,desired-max-y", &temp_val); + if (!rc) { + hbtp->des_maxy = (int) temp_val; + } else if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read desired max y\n"); + return rc; + } + + /* + * Either both DT properties i.e. Default max X and + * Desired max X should be defined simultaneously, or none + * of them should be defined. + */ + if (!((hbtp->def_maxy == 0 && hbtp->des_maxy != 0) || + (hbtp->def_maxy != 0 && hbtp->des_maxy == 0))) { + dev_err(dev, "default or desired max-Y properties are incorrect\n"); + return -EINVAL; + } + + } + return 0; } #else