From patchwork Thu Feb 16 17:50:59 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 9577833 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 04F526049F for ; Thu, 16 Feb 2017 17:52:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EC0021FE84 for ; Thu, 16 Feb 2017 17:52:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DFD0E26E81; Thu, 16 Feb 2017 17:52:13 +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.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable 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 61A991FE84 for ; Thu, 16 Feb 2017 17:52:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754704AbdBPRv7 (ORCPT ); Thu, 16 Feb 2017 12:51:59 -0500 Received: from mx1.redhat.com ([209.132.183.28]:39404 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932697AbdBPRvI (ORCPT ); Thu, 16 Feb 2017 12:51:08 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BC7E23A768F; Thu, 16 Feb 2017 17:51:08 +0000 (UTC) Received: from plouf.banquise.eu.com (ovpn-117-172.ams2.redhat.com [10.36.117.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1GHp3Zv013807; Thu, 16 Feb 2017 12:51:07 -0500 From: Benjamin Tissoires To: Dmitry Torokhov , Andrew Duggan Cc: linux-kernel@vger.kernel.org, linux-input@vger.kernel.org Subject: [PATCH v2 2/3] Input: synaptics - allocate a Synaptics Intertouch device Date: Thu, 16 Feb 2017 18:50:59 +0100 Message-Id: <20170216175100.1668-3-benjamin.tissoires@redhat.com> In-Reply-To: <20170216175100.1668-1-benjamin.tissoires@redhat.com> References: <20170216175100.1668-1-benjamin.tissoires@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Thu, 16 Feb 2017 17:51:08 +0000 (UTC) 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 Most of the Synaptics devices are connected through PS/2 and a different bus (SMBus or HID over I2C). The secondary bus capability is indicated by the InterTouch bit in extended capability 0x0C. When we encounter such a device, we can create a platform device with the information gathered through the PS/2 enumeration as some information might be missing through the other bus. Using a platform device allows to not add any dependency on the psmouse driver. We only enable the InterTouch device to be created for the laptops registered with the top software button property or those we know that are functional. In the future, we might change the default to always rely on the InterTouch bus. Currently, users can enable/disable the feature with the psmouse parameter synaptics_intertouch. The SMBus devices keep their PS/2 connection alive. If the initialization process goes too far (psmouse_activate called), the device disconnects from the I2C bus and stays on the PS/2 bus. We need to be sure the psmouse driver will stop communicating with the device (and the pass-through trackstick too). This part is not addressed here but will be in a following patch. The HID over I2C devices are enumerated through the ACPI DSDT, and their PS/2 device also exports the InterTouch bit in the extended capability 0x0C. However, the firmware keeps its I2C connection open even after going further in the PS/2 initialization. We don't need to take extra precautions with those device, especially because they block their PS/2 communication when HID over I2C is used. Signed-off-by: Benjamin Tissoires --- changes in v2: - do not store the platform device as psmouse will be disconnected to be replaced by a dummy serio driver. --- drivers/input/mouse/synaptics.c | 106 ++++++++++++++++++++++++++++++++++++++++ drivers/input/mouse/synaptics.h | 1 + 2 files changed, 107 insertions(+) diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 597ee4b..c71a500 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include "psmouse.h" #include "synaptics.h" @@ -70,6 +72,21 @@ /* maximum ABS_MT_POSITION displacement (in mm) */ #define DMAX 10 +/* + * The newest Synaptics device can use a secondary bus (called InterTouch) which + * provides a better bandwidth and allow a better control of the touchpads. + * This is used to decide if we need to use this bus or not. + */ +enum { + SYNAPTICS_INTERTOUCH_NOT_SET = -1, + SYNAPTICS_INTERTOUCH_OFF, + SYNAPTICS_INTERTOUCH_ON, +}; + +static int synaptics_intertouch = SYNAPTICS_INTERTOUCH_NOT_SET; +module_param_named(synaptics_intertouch, synaptics_intertouch, int, 0644); +MODULE_PARM_DESC(synaptics_intertouch, "Use a secondary bus for the Synaptics device."); + /***************************************************************************** * Stuff we need even when we do not want native Synaptics support ****************************************************************************/ @@ -218,6 +235,92 @@ static const char * const forcepad_pnp_ids[] = { NULL }; +static const char * const smbus_pnp_ids[] = { + /* all of the topbuttonpad_pnp_ids are valid, we just add some extras */ + "LEN0048", /* X1 Carbon 3 */ + "LEN0046", /* X250 */ + "LEN004a", /* W541 */ + "LEN200f", /* T450s */ +}; + +static int rmi4_id; + +static int synaptics_create_intertouch(struct psmouse *psmouse) +{ + struct synaptics_data *priv = psmouse->private; + struct platform_device_info pdevinfo; + struct platform_device *pdev; + struct rmi_device_platform_data pdata = { + .sensor_pdata = { + .sensor_type = rmi_sensor_touchpad, + .axis_align.flip_y = true, + /* to prevent cursors jumps: */ + .kernel_tracking = true, + }, + .f30_data = { + .buttonpad = SYN_CAP_CLICKPAD(priv->ext_cap_0c), + .trackstick_buttons = + !!SYN_CAP_EXT_BUTTONS_STICK(priv->ext_cap_10), + }, + }; + + pdata.sensor_pdata.topbuttonpad = + psmouse_matches_pnp_id(psmouse, topbuttonpad_pnp_ids) && + !SYN_CAP_EXT_BUTTONS_STICK(priv->ext_cap_10); + + memset(&pdevinfo, 0, sizeof(pdevinfo)); + pdevinfo.name = "rmi4"; + pdevinfo.id = rmi4_id++; + pdevinfo.data = &pdata; + pdevinfo.size_data = sizeof(pdata); + pdevinfo.parent = &psmouse->ps2dev.serio->dev; + + pdev = platform_device_register_full(&pdevinfo); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); + + return 0; +} + +static int synaptics_remove_intertouch_device(struct device *dev, void *data) +{ + struct platform_device *pdev = to_platform_device(dev); + + if (strncmp("rmi4", dev_name(dev), 4)) + return 0; + + platform_device_unregister(pdev); + + return 0; +} + +/** + * synaptics_setup_intertouch - called once the PS/2 devices are enumerated + * and decides to instantiate a SMBus InterTouch device. + */ +static void synaptics_setup_intertouch(struct psmouse *psmouse) +{ + int ret; + + /* first remove any remnant platform intertouch devices */ + bus_for_each_dev(&platform_bus_type, NULL, NULL, + synaptics_remove_intertouch_device); + + if (synaptics_intertouch == SYNAPTICS_INTERTOUCH_OFF) + return; + + if (synaptics_intertouch == SYNAPTICS_INTERTOUCH_NOT_SET) { + if (!psmouse_matches_pnp_id(psmouse, topbuttonpad_pnp_ids) && + !psmouse_matches_pnp_id(psmouse, smbus_pnp_ids)) + return; + } + + psmouse_info(psmouse, "device also supported by an other bus.\n"); + ret = synaptics_create_intertouch(psmouse); + if (ret) + psmouse_info(psmouse, + "unable to create intertouch device.\n"); +} /***************************************************************************** * Synaptics communications functions ****************************************************************************/ @@ -1546,6 +1649,9 @@ static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) } } + if (SYN_CAP_INTERTOUCH(priv->ext_cap_0c)) + synaptics_setup_intertouch(psmouse); + return 0; init_fail: diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index 116ae25..ccbd3c5 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h @@ -90,6 +90,7 @@ #define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) #define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400) #define SYN_CAP_IMAGE_SENSOR(ex0c) ((ex0c) & 0x000800) +#define SYN_CAP_INTERTOUCH(ex0c) ((ex0c) & 0x004000) /* * The following descibes response for the 0x10 query.