From patchwork Fri Jan 26 19:19:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 10186889 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 214D8601D5 for ; Fri, 26 Jan 2018 19:19:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0E00F29679 for ; Fri, 26 Jan 2018 19:19:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 01F77297ED; Fri, 26 Jan 2018 19:19:51 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C43AD29679 for ; Fri, 26 Jan 2018 19:19:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753142AbeAZTTu (ORCPT ); Fri, 26 Jan 2018 14:19:50 -0500 Received: from mail-pg0-f66.google.com ([74.125.83.66]:42720 "EHLO mail-pg0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752924AbeAZTTs (ORCPT ); Fri, 26 Jan 2018 14:19:48 -0500 Received: by mail-pg0-f66.google.com with SMTP id q67so843348pga.9 for ; Fri, 26 Jan 2018 11:19:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=tJyFuOgL42WGlOQk16LYhvSKB3EPTPj+qSt9HWg9WTY=; b=if5RPJqPgxxCatcSysTz6mUVH88b3fVNup2pxLIsmfeZ8ZTSJjOI4s1FEJccHTCJHi k3iK/2cRsX0/n+yC12dc5n1uWK/9PxmQCctFwKGsqfFam/HLeDxmmLmQqE0fC0r/OR1D Cq+p53nk5EHT762tlzDfhgSfNQBVNJ020pL22/N9OMg8jP/9LHBecsnU5rviS1uhOYVi Et5BLU3o3YO7bEPk/kAVTKcfT/1vYZgjsgUZwMJXvBcWX8unsZQ1uXu9I7hJRUSNA2w4 /VMiKCh3l7/gCDyeVYzOsKehgkCAN2diWPUFpGxtyXEnvJrf6QYhdMJ/rc3DSyOkr3nO juAQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=tJyFuOgL42WGlOQk16LYhvSKB3EPTPj+qSt9HWg9WTY=; b=RZuymArm4PisqBB4lx2y863qaPcs+ldRuEh9N0WRsnj1BppEXli1k4hGTaHlhSfnlr k8TNoYOG++jZDj4vCFALfwS6WqaRCLbNWhosLsZVyvZ8JjLplZnNSztrrx09DYLjJAUC wTedBS02CG9Z2VzlXm5ZFXnxdBcj75E7C1aVU7uoEuhl/lBzXcN5HKnylAEK4p5drmZP hNv5vwFhSv/86d0yuX6EddH2SNyakMmxoiwvYhOAMZJaJYhBmUpp5LY+BYVMdLiTp9rE 8JlHyQem+YYFvGLKtSl/hwo9T8Xe2CQErOyElmq1wblHi2rO5rEMjTf9fjTkf8glCiyf VkWA== X-Gm-Message-State: AKwxytcvWZgnTFLtvyMu8Ghq9c2coRfBQNUQxfHeemvldevlhtTSpd/t nmdCD9du6tttqEdoxksAV4T4Fvcb X-Google-Smtp-Source: AH8x227ZSd/7cT/peXQy8bQLITQbl0qScdgBCu3QaRBH86rsWNXJmti7+l65GB6W+MUE/BG4Ocu9zw== X-Received: by 10.99.178.19 with SMTP id x19mr15950809pge.31.1516994387881; Fri, 26 Jan 2018 11:19:47 -0800 (PST) Received: from dtor-ws ([2620:0:1000:1611:da80:8749:c06f:9515]) by smtp.gmail.com with ESMTPSA id p20sm16162890pfh.100.2018.01.26.11.19.46 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 26 Jan 2018 11:19:47 -0800 (PST) Date: Fri, 26 Jan 2018 11:19:45 -0800 From: Dmitry Torokhov To: Marcin Niestroj Cc: Bastien Nocera , Antonio Ospite , linux-input@vger.kernel.org Subject: Re: [PATCH v3 3/3] Input: goodix - use generic touchscreen_properties Message-ID: <20180126191945.q3sx2pcs7rvpil33@dtor-ws> References: <20180125190829.8968-1-m.niestroj@grinn-global.com> <20180125190829.8968-4-m.niestroj@grinn-global.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20180125190829.8968-4-m.niestroj@grinn-global.com> User-Agent: NeoMutt/20170609 (1.8.3) Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Hi Marcin, On Thu, Jan 25, 2018 at 08:08:29PM +0100, Marcin Niestroj wrote: > Use touchscreen_properties structure instead of implementing all > properties by our own. It allows us to reuse generic code for parsing > device-tree properties (which was implemented manually in the driver > for now). Additionally, it allows us to report events using generic > touchscreen_report_pos(), which automatically handles inverted and > swapped axes. > > Developed and tested on custom DT-based device with gt1151 touch > panel. > > Signed-off-by: Marcin Niestroj > --- > Changes v2 -> v3 (suggested by Bastien): > - fix commit description > > Changes v1 -> v2: > - rebased on patches 1 and 2 in series > - added description of test board in changelog (suggested by Bastien) > > drivers/input/touchscreen/goodix.c | 93 ++++++++++++++------------------------ > 1 file changed, 33 insertions(+), 60 deletions(-) > > diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c > index dc832890f6d3..f82101cd9c04 100644 > --- a/drivers/input/touchscreen/goodix.c > +++ b/drivers/input/touchscreen/goodix.c > @@ -22,6 +22,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -43,11 +44,7 @@ struct goodix_ts_data { > struct i2c_client *client; > struct input_dev *input_dev; > const struct goodix_chip_data *chip; > - int abs_x_max; > - int abs_y_max; > - bool swapped_x_y; > - bool inverted_x; > - bool inverted_y; > + struct touchscreen_properties prop; > unsigned int max_touch_num; > unsigned int int_trigger_type; > struct gpio_desc *gpiod_int; > @@ -295,24 +292,10 @@ static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data) > int input_y = get_unaligned_le16(&coor_data[3]); > int input_w = get_unaligned_le16(&coor_data[5]); > > - /* Inversions have to happen before axis swapping */ > - if (!ts->swapped_x_y) { > - if (ts->inverted_x) > - input_x = ts->abs_x_max - input_x; > - if (ts->inverted_y) > - input_y = ts->abs_y_max - input_y; > - } else { > - if (ts->inverted_x) > - input_x = ts->abs_y_max - input_x; > - if (ts->inverted_y) > - input_y = ts->abs_x_max - input_y; > - swap(input_x, input_y); > - } > - > input_mt_slot(ts->input_dev, id); > input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true); > - input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x); > - input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, input_y); > + touchscreen_report_pos(ts->input_dev, &ts->prop, input_x, input_y, > + true); > input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, input_w); > input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, input_w); > } > @@ -585,6 +568,7 @@ static int goodix_get_gpio_config(struct goodix_ts_data *ts) > static void goodix_read_config(struct goodix_ts_data *ts) > { > u8 config[GOODIX_CONFIG_MAX_LENGTH]; > + int x_max, y_max; > int error; > > error = goodix_i2c_read(ts->client, ts->chip->config_addr, > @@ -593,37 +577,34 @@ static void goodix_read_config(struct goodix_ts_data *ts) > dev_warn(&ts->client->dev, > "Error reading config (%d), using defaults\n", > error); > - ts->abs_x_max = GOODIX_MAX_WIDTH - 1; > - ts->abs_y_max = GOODIX_MAX_HEIGHT - 1; > - if (ts->swapped_x_y) > - swap(ts->abs_x_max, ts->abs_y_max); > + x_max = GOODIX_MAX_WIDTH; > + y_max = GOODIX_MAX_HEIGHT; > ts->int_trigger_type = GOODIX_INT_TRIGGER; > ts->max_touch_num = GOODIX_MAX_CONTACTS; > - return; > + goto input_set_params; > } > > - ts->abs_x_max = get_unaligned_le16(&config[RESOLUTION_LOC]) - 1; > - ts->abs_y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]) - 1; > - if (ts->swapped_x_y) > - swap(ts->abs_x_max, ts->abs_y_max); > + x_max = get_unaligned_le16(&config[RESOLUTION_LOC]); > + y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]); > ts->int_trigger_type = config[TRIGGER_LOC] & 0x03; > ts->max_touch_num = config[MAX_CONTACTS_LOC] & 0x0f; > - if (!ts->abs_x_max || !ts->abs_y_max || !ts->max_touch_num) { > + if (!x_max || !y_max || !ts->max_touch_num) { > dev_err(&ts->client->dev, > "Invalid config, using defaults\n"); > - ts->abs_x_max = GOODIX_MAX_WIDTH - 1; > - ts->abs_y_max = GOODIX_MAX_HEIGHT - 1; > - if (ts->swapped_x_y) > - swap(ts->abs_x_max, ts->abs_y_max); > + x_max = GOODIX_MAX_WIDTH; > + y_max = GOODIX_MAX_HEIGHT; > ts->max_touch_num = GOODIX_MAX_CONTACTS; > } > > - if (dmi_check_system(rotated_screen)) { > - ts->inverted_x = true; > - ts->inverted_y = true; > - dev_dbg(&ts->client->dev, > - "Applying '180 degrees rotated screen' quirk\n"); > - } > +input_set_params: > + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, > + 0, x_max - 1, 0, 0); > + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, > + 0, y_max - 1, 0, 0); > + input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); > + input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); > + input_mt_init_slots(ts->input_dev, ts->max_touch_num, > + INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); > } > > /** > @@ -698,16 +679,6 @@ static int goodix_request_input_dev(struct goodix_ts_data *ts) > return -ENOMEM; > } > > - input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, > - 0, ts->abs_x_max, 0, 0); > - input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, > - 0, ts->abs_y_max, 0, 0); > - input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); > - input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); > - > - input_mt_init_slots(ts->input_dev, ts->max_touch_num, > - INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); > - > ts->input_dev->name = "Goodix Capacitive TouchScreen"; > ts->input_dev->phys = "input/ts"; > ts->input_dev->id.bustype = BUS_I2C; > @@ -742,19 +713,21 @@ static int goodix_configure_dev(struct goodix_ts_data *ts) > { > int error; > > - ts->swapped_x_y = device_property_read_bool(&ts->client->dev, > - "touchscreen-swapped-x-y"); > - ts->inverted_x = device_property_read_bool(&ts->client->dev, > - "touchscreen-inverted-x"); > - ts->inverted_y = device_property_read_bool(&ts->client->dev, > - "touchscreen-inverted-y"); > - > - goodix_read_config(ts); > - > error = goodix_request_input_dev(ts); > if (error) > return error; > > + goodix_read_config(ts); > + > + touchscreen_parse_properties(ts->input_dev, true, &ts->prop); You want to do reading of the config and parsing properties and applying them to the input device before input device is registered. Actually, you want to do that before you call input_mt_init_slots() to make sure multitouch and single-touch data is consistend (ABS_MT_POSITION_X/Y vs ABS_X/Y). Can you please try the version below (note that I sqashed all your 3 patches in one as, as I mentioed, I do not see why they need to be split in the first place). Thanks. diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index ecec8eb17f28b..9736c83dd418f 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -43,11 +44,7 @@ struct goodix_ts_data { struct i2c_client *client; struct input_dev *input_dev; const struct goodix_chip_data *chip; - int abs_x_max; - int abs_y_max; - bool swapped_x_y; - bool inverted_x; - bool inverted_y; + struct touchscreen_properties prop; unsigned int max_touch_num; unsigned int int_trigger_type; struct gpio_desc *gpiod_int; @@ -160,7 +157,7 @@ static int goodix_i2c_read(struct i2c_client *client, u16 reg, u8 *buf, int len) { struct i2c_msg msgs[2]; - u16 wbuf = cpu_to_be16(reg); + __be16 wbuf = cpu_to_be16(reg); int ret; msgs[0].flags = 0; @@ -295,18 +292,10 @@ static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data) int input_y = get_unaligned_le16(&coor_data[3]); int input_w = get_unaligned_le16(&coor_data[5]); - /* Inversions have to happen before axis swapping */ - if (ts->inverted_x) - input_x = ts->abs_x_max - input_x; - if (ts->inverted_y) - input_y = ts->abs_y_max - input_y; - if (ts->swapped_x_y) - swap(input_x, input_y); - input_mt_slot(ts->input_dev, id); input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true); - input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x); - input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, input_y); + touchscreen_report_pos(ts->input_dev, &ts->prop, + input_x, input_y, true); input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, input_w); input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, input_w); } @@ -579,44 +568,27 @@ static int goodix_get_gpio_config(struct goodix_ts_data *ts) static void goodix_read_config(struct goodix_ts_data *ts) { u8 config[GOODIX_CONFIG_MAX_LENGTH]; + int x_max, y_max; int error; error = goodix_i2c_read(ts->client, ts->chip->config_addr, config, ts->chip->config_len); if (error) { - dev_warn(&ts->client->dev, - "Error reading config (%d), using defaults\n", + dev_warn(&ts->client->dev, "Error reading config: %d\n", error); - ts->abs_x_max = GOODIX_MAX_WIDTH; - ts->abs_y_max = GOODIX_MAX_HEIGHT; - if (ts->swapped_x_y) - swap(ts->abs_x_max, ts->abs_y_max); ts->int_trigger_type = GOODIX_INT_TRIGGER; ts->max_touch_num = GOODIX_MAX_CONTACTS; return; } - ts->abs_x_max = get_unaligned_le16(&config[RESOLUTION_LOC]); - ts->abs_y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]); - if (ts->swapped_x_y) - swap(ts->abs_x_max, ts->abs_y_max); ts->int_trigger_type = config[TRIGGER_LOC] & 0x03; ts->max_touch_num = config[MAX_CONTACTS_LOC] & 0x0f; - if (!ts->abs_x_max || !ts->abs_y_max || !ts->max_touch_num) { - dev_err(&ts->client->dev, - "Invalid config, using defaults\n"); - ts->abs_x_max = GOODIX_MAX_WIDTH; - ts->abs_y_max = GOODIX_MAX_HEIGHT; - if (ts->swapped_x_y) - swap(ts->abs_x_max, ts->abs_y_max); - ts->max_touch_num = GOODIX_MAX_CONTACTS; - } - if (dmi_check_system(rotated_screen)) { - ts->inverted_x = true; - ts->inverted_y = true; - dev_dbg(&ts->client->dev, - "Applying '180 degrees rotated screen' quirk\n"); + x_max = get_unaligned_le16(&config[RESOLUTION_LOC]); + y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]); + if (x_max && y_max) { + input_abs_set_max(ts->input_dev, ABS_MT_POSITION_X, x_max - 1); + input_abs_set_max(ts->input_dev, ABS_MT_POSITION_Y, y_max - 1); } } @@ -676,32 +648,28 @@ static int goodix_i2c_test(struct i2c_client *client) } /** - * goodix_request_input_dev - Allocate, populate and register the input device + * goodix_configure_dev - Finish device initialization * * @ts: our goodix_ts_data pointer * - * Must be called during probe + * Must be called from probe to finish initialization of the device. + * Contains the common initialization code for both devices that + * declare gpio pins and devices that do not. It is either called + * directly from probe or from request_firmware_wait callback. */ -static int goodix_request_input_dev(struct goodix_ts_data *ts) +static int goodix_configure_dev(struct goodix_ts_data *ts) { int error; + ts->int_trigger_type = GOODIX_INT_TRIGGER; + ts->max_touch_num = GOODIX_MAX_CONTACTS; + ts->input_dev = devm_input_allocate_device(&ts->client->dev); if (!ts->input_dev) { dev_err(&ts->client->dev, "Failed to allocate input device."); return -ENOMEM; } - input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, - 0, ts->abs_x_max, 0, 0); - input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, - 0, ts->abs_y_max, 0, 0); - input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); - input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); - - input_mt_init_slots(ts->input_dev, ts->max_touch_num, - INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); - ts->input_dev->name = "Goodix Capacitive TouchScreen"; ts->input_dev->phys = "input/ts"; ts->input_dev->id.bustype = BUS_I2C; @@ -712,42 +680,49 @@ static int goodix_request_input_dev(struct goodix_ts_data *ts) /* Capacitive Windows/Home button on some devices */ input_set_capability(ts->input_dev, EV_KEY, KEY_LEFTMETA); - error = input_register_device(ts->input_dev); - if (error) { - dev_err(&ts->client->dev, - "Failed to register input device: %d", error); - return error; - } + input_set_capability(ts->input_dev, EV_ABS, ABS_MT_POSITION_X); + input_set_capability(ts->input_dev, EV_ABS, ABS_MT_POSITION_Y); + input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); - return 0; -} + /* Read configuration and apply touchscreen parameters */ + goodix_read_config(ts); -/** - * goodix_configure_dev - Finish device initialization - * - * @ts: our goodix_ts_data pointer - * - * Must be called from probe to finish initialization of the device. - * Contains the common initialization code for both devices that - * declare gpio pins and devices that do not. It is either called - * directly from probe or from request_firmware_wait callback. - */ -static int goodix_configure_dev(struct goodix_ts_data *ts) -{ - int error; + /* Try overriding touchscreen parameters via device properties */ + touchscreen_parse_properties(ts->input_dev, true, &ts->prop); - ts->swapped_x_y = device_property_read_bool(&ts->client->dev, - "touchscreen-swapped-x-y"); - ts->inverted_x = device_property_read_bool(&ts->client->dev, - "touchscreen-inverted-x"); - ts->inverted_y = device_property_read_bool(&ts->client->dev, - "touchscreen-inverted-y"); + if (!ts->prop.max_x || !ts->prop.max_y || !ts->max_touch_num) { + dev_err(&ts->client->dev, "Invalid config, using defaults\n"); + ts->prop.max_x = GOODIX_MAX_WIDTH - 1; + ts->prop.max_y = GOODIX_MAX_HEIGHT - 1; + ts->max_touch_num = GOODIX_MAX_CONTACTS; + input_abs_set_max(ts->input_dev, + ABS_MT_POSITION_X, ts->prop.max_x); + input_abs_set_max(ts->input_dev, + ABS_MT_POSITION_Y, ts->prop.max_y); + } - goodix_read_config(ts); + if (dmi_check_system(rotated_screen)) { + ts->prop.invert_x = true; + ts->prop.invert_y = true; + dev_dbg(&ts->client->dev, + "Applying '180 degrees rotated screen' quirk\n"); + } - error = goodix_request_input_dev(ts); - if (error) + error = input_mt_init_slots(ts->input_dev, ts->max_touch_num, + INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); + if (error) { + dev_err(&ts->client->dev, + "Failed to initialize MT slots: %d", error); + return error; + } + + error = input_register_device(ts->input_dev); + if (error) { + dev_err(&ts->client->dev, + "Failed to register input device: %d", error); return error; + } ts->irq_flags = goodix_irq_flags[ts->int_trigger_type] | IRQF_ONESHOT; error = goodix_request_irq(ts);