From patchwork Wed Aug 28 09:53:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jongpil Jung X-Patchwork-Id: 11118419 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 82D33184E for ; Wed, 28 Aug 2019 09:53:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 624AA2054F for ; Wed, 28 Aug 2019 09:53:57 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="mA91kive" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726292AbfH1Jx4 (ORCPT ); Wed, 28 Aug 2019 05:53:56 -0400 Received: from mail-pf1-f194.google.com ([209.85.210.194]:42906 "EHLO mail-pf1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726272AbfH1Jx4 (ORCPT ); Wed, 28 Aug 2019 05:53:56 -0400 Received: by mail-pf1-f194.google.com with SMTP id i30so1372673pfk.9 for ; Wed, 28 Aug 2019 02:53:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=vjiSpM+ep/75nQ1vZWqSkhpYEt77QZKnrxYYvma4X3w=; b=mA91kive7zKdE3YkuUpGUofFxs7Aykrrl07AiGDqf/UBWhDBVyWiwHCyq+xqnVAHdc lTFcVF6+fcbKT01UtIITrSSzGuPdc/zHpzAZHwq/iKRaMz6rCtt3aoQwL9suCv0r7BWk k7d4KUsjwkITx9sWBqwWTvyb28gpUXUMrydCh2ZaK51p1UAJ9e/zIm6Vurd97XE6Ysl3 koLN9VYQB0NQlbKVFVUSFRVrChMagADADcI5FwHKXOTH6W3uQkDCNyNpe7gU2uzlNbb+ yCeBx/2fvNcmapChihsHuhY2tgJEVR1dQbz1XZasisKTdbv35paZZnbbepFHBeksgreh jiNQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=vjiSpM+ep/75nQ1vZWqSkhpYEt77QZKnrxYYvma4X3w=; b=WFrtzrntcQxmbjXmwD4Wv4LPvPMoH+l1qfuUY7qqAAk4Snts+xlY7vr1Rdabs9ADbY ykK2mYnJHqt6cOW8yFWqeMJAy7TTJfGi0Tq4+3QkGdQdXvU/fM5j1I7szeV634N9Tcsw pspzGS6xi2KASCrsA0VvKFx5qox6ria6NCmx7yA0a7aYWOa8+QGENhhWXMQ2L1STPn53 RNPeH76rbKLyXDZYd+06X5Er4diSaUCWwwaYDeQ5NDJ5nijkIyYD6b92esQ6JDV6d+GU bbqI4+XXrad6DlH0YOB9jDyTDV0egCQrGVa9Wo1WNIG3WcmvJdWJnu9dxEg3y3xhbhxb RLRQ== X-Gm-Message-State: APjAAAWvZnB2kboi3wJaots5/nWsL6AUvn41g5SOFXHMlJuBXaUhxWRS V4TsN508f7MLdYz57VKlEUR3yoq9 X-Google-Smtp-Source: APXvYqxntn02doHrWoUg7f+Wi8ZXnF9oL0Ch5iUCmCCRB+swythX+ha53L82AcSrAQXI/xo6zfVKBQ== X-Received: by 2002:a63:5754:: with SMTP id h20mr2595132pgm.195.1566986035362; Wed, 28 Aug 2019 02:53:55 -0700 (PDT) Received: from localhost.localdomain ([39.117.32.11]) by smtp.gmail.com with ESMTPSA id m13sm2101432pgn.57.2019.08.28.02.53.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 28 Aug 2019 02:53:54 -0700 (PDT) From: Jongpil Jung To: linux-input@vger.kernel.org Cc: Jongpil Jung Subject: [PATCH 1/8] Input: atmel_mxt_ts - eanble calibration via sysfs Date: Wed, 28 Aug 2019 18:53:42 +0900 Message-Id: <20190828095349.30607-1-jongpuls@gmail.com> X-Mailer: git-send-email 2.17.1 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org From: Jongpil Jung Make interface to calibrate touchscreen ic so that we can do calibration in user space. Change-Id: Ied8262d6451ae4478e87efc205bf07708422027f --- drivers/input/touchscreen/atmel_mxt_ts.c | 31 ++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 24c4b691b1c9..4fe2059fa3c1 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -189,6 +189,7 @@ enum t100_type { /* Delay times */ #define MXT_BACKUP_TIME 50 /* msec */ +#define MXT_CAL_TIME 25 /* msec */ #define MXT_RESET_GPIO_TIME 20 /* msec */ #define MXT_RESET_INVALID_CHG 100 /* msec */ #define MXT_RESET_TIME 200 /* msec */ @@ -753,6 +754,21 @@ static int mxt_write_object(struct mxt_data *data, return mxt_write_reg(data->client, reg + offset, val); } +static int mxt_recalibrate(struct mxt_data *data) +{ + struct device *dev = &data->client->dev; + int error; + + dev_dbg(dev, "Recalibration ...\n"); + error = mxt_write_object(data, MXT_GEN_COMMAND_T6, + MXT_COMMAND_CALIBRATE, 1); + if (error) + dev_err(dev, "Recalibration failed %d\n", error); + else + msleep(MXT_CAL_TIME); + return error; +} + static void mxt_input_button(struct mxt_data *data, u8 *message) { struct input_dev *input = data->input_dev; @@ -2663,6 +2679,19 @@ static int mxt_configure_objects(struct mxt_data *data, return 0; } +static ssize_t mxt_calibrate_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct mxt_data *data = dev_get_drvdata(dev); + int ret; + + disable_irq(data->irq); + ret = mxt_recalibrate(data); + enable_irq(data->irq); + return ret ?: count; +} + /* Firmware Version is returned as Major.Minor.Build */ static ssize_t mxt_fw_version_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -2910,12 +2939,14 @@ static ssize_t mxt_update_fw_store(struct device *dev, return count; } +static DEVICE_ATTR(calibrate, S_IWUSR, NULL, mxt_calibrate_store); static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL); static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL); static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL); static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store); static struct attribute *mxt_attrs[] = { + &dev_attr_calibrate.attr, &dev_attr_fw_version.attr, &dev_attr_hw_version.attr, &dev_attr_object.attr, From patchwork Wed Aug 28 09:53:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jongpil Jung X-Patchwork-Id: 11118421 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 64B6C14F7 for ; Wed, 28 Aug 2019 09:54:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4490D2054F for ; Wed, 28 Aug 2019 09:54:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="jftNxP6m" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726300AbfH1JyL (ORCPT ); Wed, 28 Aug 2019 05:54:11 -0400 Received: from mail-pg1-f196.google.com ([209.85.215.196]:40082 "EHLO mail-pg1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726272AbfH1JyL (ORCPT ); Wed, 28 Aug 2019 05:54:11 -0400 Received: by mail-pg1-f196.google.com with SMTP id w10so1181161pgj.7 for ; Wed, 28 Aug 2019 02:54:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=9dtC7/eaK/XYH+q5ZQPPbTngcUeszJrZS9FqzY3n7IY=; b=jftNxP6m/7TAIcJ0q7gi9saP6mq68zShoBs+rSTftyYtol9+1tI/XRWP+t1z44eCok qcW6pg5SSlSeXHK3cl6kx1bxHynJEejYdSsz6RCQpjvnfKl0sVavVAFv6FHVXCrc0fKi PDEpNgx+utyVs2t/hmLR49ZchSqe3tE+Nu4NHqs5Ezp6Wqdwezf3OWTr4JWZ6kX55kPc HVc/AuvGlhh3Im2t56PVbaUv0foAX4TLYruZsbzE/+lNNDm1TS3kj/Ziqy14Pqi3WEP6 iObL3De0vRMnxVsUr7BSwlmqMLXg7OPfFnlGQKztVfFMv2FCmVEdzWwfw0/Jmo5Yr3Oz 4TKA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=9dtC7/eaK/XYH+q5ZQPPbTngcUeszJrZS9FqzY3n7IY=; b=A/ePUkdyoYMYVZuWx3uwhlYGarYWWcRHalilnVDpoWemB2+Skz5u5RMSV9mzOulcOe hfaX+gxAt9z804f/NtH/toyheDc0jet89dAdXvILq/mgPJzaYQlZ0XplmUrgii1WoioJ lFgrcpDmWZhAeXKu26ptfro5tncSWdM34s91Yb72GhitbQi0ciU4dMX0IyCTwKSGy2OG Qf92n9v8dbnpsQ4PDAK91Do/J16OdKO3iz1ikYX8xciwiv9sDEWRCmcXBlWyaH2paMY3 VIXsxYEjkNnStsjE5OTnio+6dZ6ZZ7oEF9g+hYcUeapXt5WrQePu63yRN4/OO894rvzK bQNQ== X-Gm-Message-State: APjAAAXS8JHipAYQ4vhOo62FTPwoT7Csp9+6wed4E3qVmbqoj6iY0Tkz XaZBkN47zdwkrTViyyKsXvk8+Sv0 X-Google-Smtp-Source: APXvYqwhUhsyGAQo/PiLNqhOP5ppnNRRpWQZvJastwkySkE9nbC+RyYRYf9/mcH6w4rWwIpmeNpinA== X-Received: by 2002:a63:5b23:: with SMTP id p35mr2640193pgb.366.1566986050468; Wed, 28 Aug 2019 02:54:10 -0700 (PDT) Received: from localhost.localdomain ([39.117.32.11]) by smtp.gmail.com with ESMTPSA id m13sm2101432pgn.57.2019.08.28.02.54.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 28 Aug 2019 02:54:10 -0700 (PDT) From: Jongpil Jung To: linux-input@vger.kernel.org Cc: Jongpil Jung Subject: [PATCH 2/8] Input: atmel_mxt_ts - show info/confing checksum. Date: Wed, 28 Aug 2019 18:53:43 +0900 Message-Id: <20190828095349.30607-2-jongpuls@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190828095349.30607-1-jongpuls@gmail.com> References: <20190828095349.30607-1-jongpuls@gmail.com> Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org From: Jongpil Jung To check current touchscreen config, we need to read information and config checksum. With patch, we can check checksum in user space via sysfs easily. Change-Id: I0328945cec10f142bd5670bfd7a3133de3f473db --- drivers/input/touchscreen/atmel_mxt_ts.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 4fe2059fa3c1..cabe746607fc 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -2692,6 +2692,13 @@ static ssize_t mxt_calibrate_store(struct device *dev, return ret ?: count; } +static ssize_t mxt_config_csum_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mxt_data *data = dev_get_drvdata(dev); + return scnprintf(buf, PAGE_SIZE, "%06x\n", data->config_crc); +} + /* Firmware Version is returned as Major.Minor.Build */ static ssize_t mxt_fw_version_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -2712,6 +2719,13 @@ static ssize_t mxt_hw_version_show(struct device *dev, info->family_id, info->variant_id); } +static ssize_t mxt_info_csum_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mxt_data *data = dev_get_drvdata(dev); + return scnprintf(buf, PAGE_SIZE, "%06x\n", data->info_crc); +} + static ssize_t mxt_show_instance(char *buf, int count, struct mxt_object *object, int instance, const u8 *val) @@ -2940,15 +2954,19 @@ static ssize_t mxt_update_fw_store(struct device *dev, } static DEVICE_ATTR(calibrate, S_IWUSR, NULL, mxt_calibrate_store); +static DEVICE_ATTR(config_csum, S_IRUGO, mxt_config_csum_show, NULL); static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL); static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL); +static DEVICE_ATTR(info_csum, S_IRUGO, mxt_info_csum_show, NULL); static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL); static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store); static struct attribute *mxt_attrs[] = { &dev_attr_calibrate.attr, + &dev_attr_config_csum.attr, &dev_attr_fw_version.attr, &dev_attr_hw_version.attr, + &dev_attr_info_csum.attr, &dev_attr_object.attr, &dev_attr_update_fw.attr, NULL From patchwork Wed Aug 28 09:53:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jongpil Jung X-Patchwork-Id: 11118423 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B270C14F7 for ; Wed, 28 Aug 2019 09:54:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 929A12054F for ; Wed, 28 Aug 2019 09:54:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="DYAVmy+7" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726339AbfH1JyO (ORCPT ); Wed, 28 Aug 2019 05:54:14 -0400 Received: from mail-pf1-f181.google.com ([209.85.210.181]:41492 "EHLO mail-pf1-f181.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726272AbfH1JyO (ORCPT ); Wed, 28 Aug 2019 05:54:14 -0400 Received: by mail-pf1-f181.google.com with SMTP id 196so1378467pfz.8 for ; Wed, 28 Aug 2019 02:54:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=4WJHzd9uWBViuZ9IZrTOSPHXv7sk2NICbX2PeiAv/jI=; b=DYAVmy+7u2oRkFjPDU15rdBpykd0dOzsSMJtloA3Mtt9hSUh3zl12HUGVRQIQ93Qvf xhrZ8P4tZ+1NJRIwCkyfJly0a53gEzEsxUaYshroMfUHgiz2wV6Rb0J80lQjWM4Om9JH bVKcdH44Ri5N5Hcnyjv2o/pAHngv5Ch8CdV5xPECP8069p4ZZRFkDXhabCCkpROj0QoM mwHAVtkgQbvstZd2PlC4n8ksBScZ8KmlGbEc4+RoyAEVosZyG8HbdgNM4y8MigxXN1ME aGhy9RcXdWzNPgT8jtIFVwU0Ho6CdprIqncAC+eTC9cnUpE9/SVhr9XM6ZAeSkLlIR5+ fMCA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=4WJHzd9uWBViuZ9IZrTOSPHXv7sk2NICbX2PeiAv/jI=; b=TdNGcIUjwfpdy+uIAPMRDpnYGA+lJqIn65P+9gK0EeoEd3IihfD+MaNgMgV5Q9aPMa ibmZ4YgloieTJmXArrC/SNxgRs/tx9/bPmvm/C1zwX+/hl8MBuhgE871GpPsfOGhYizZ TiEnLMq8utZ+Xkmuw1szD1x2kiPRMBrOe/7DKkVC/vGzEALc0U4h2n8WFvWrgOKBKB3N GFtJdpLubzwHeO0RiIk5e2Q3Zw6FB8RN/II/uA2MhjESlv5kX4os9H4yK4OFtxt/tB2B ft1izCL5MPVJ3tKKxKq9m5neix06ol5Plc+ThX644OEjIH4LGCiPvoSWpJXG8tB6OANZ mK4A== X-Gm-Message-State: APjAAAVKp13UV1b4+9DJN1V0M6CtBrOUN462XxhZqnNbIGHDu8bTQp9l FEG0a/tzsX+fir5G4xLiPIKc18n5 X-Google-Smtp-Source: APXvYqxmqFn+HgRuaoOieJAwGzJcw3XPs+Y5Guz/Xe5xEXAWXd3m8etlcNkSfaoMwR6Pya91Hs0xmA== X-Received: by 2002:a62:144b:: with SMTP id 72mr3687239pfu.42.1566986053010; Wed, 28 Aug 2019 02:54:13 -0700 (PDT) Received: from localhost.localdomain ([39.117.32.11]) by smtp.gmail.com with ESMTPSA id m13sm2101432pgn.57.2019.08.28.02.54.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 28 Aug 2019 02:54:12 -0700 (PDT) From: Jongpil Jung To: linux-input@vger.kernel.org Cc: Jongpil Jung Subject: [PATCH 3/8] Input: atmel_mxt_ts - add interface to backup current cfg to nvram. Date: Wed, 28 Aug 2019 18:53:44 +0900 Message-Id: <20190828095349.30607-3-jongpuls@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190828095349.30607-1-jongpuls@gmail.com> References: <20190828095349.30607-1-jongpuls@gmail.com> Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org From: Jongpil Jung To backup current config, we can store current config into nvram. Change-Id: Ibea246526a9e586d89e226cfb058d40829fb2a42 --- drivers/input/touchscreen/atmel_mxt_ts.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index cabe746607fc..cb3a608f60bf 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -2679,6 +2679,23 @@ static int mxt_configure_objects(struct mxt_data *data, return 0; } +static ssize_t mxt_backupnv_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct mxt_data *data = dev_get_drvdata(dev); + int ret; + + /* Backup non-volatile memory */ + ret = mxt_write_object(data, MXT_GEN_COMMAND_T6, + MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE); + if (ret) + return ret; + msleep(MXT_BACKUP_TIME); + + return count; +} + static ssize_t mxt_calibrate_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -2953,6 +2970,7 @@ static ssize_t mxt_update_fw_store(struct device *dev, return count; } +static DEVICE_ATTR(backupnv, S_IWUSR, NULL, mxt_backupnv_store); static DEVICE_ATTR(calibrate, S_IWUSR, NULL, mxt_calibrate_store); static DEVICE_ATTR(config_csum, S_IRUGO, mxt_config_csum_show, NULL); static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL); @@ -2962,6 +2980,7 @@ static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL); static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store); static struct attribute *mxt_attrs[] = { + &dev_attr_backupnv.attr, &dev_attr_calibrate.attr, &dev_attr_config_csum.attr, &dev_attr_fw_version.attr, From patchwork Wed Aug 28 09:53:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jongpil Jung X-Patchwork-Id: 11118425 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2079F184E for ; Wed, 28 Aug 2019 09:54:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 00A742054F for ; Wed, 28 Aug 2019 09:54:16 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hqK4c5Q3" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726341AbfH1JyQ (ORCPT ); Wed, 28 Aug 2019 05:54:16 -0400 Received: from mail-pg1-f181.google.com ([209.85.215.181]:38982 "EHLO mail-pg1-f181.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726272AbfH1JyQ (ORCPT ); Wed, 28 Aug 2019 05:54:16 -0400 Received: by mail-pg1-f181.google.com with SMTP id u17so1184078pgi.6 for ; Wed, 28 Aug 2019 02:54:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=fxcLkCiIJRwl4RWn8+1v7sT5YlgbZRj3mI8Z1w4zYhI=; b=hqK4c5Q3A0PHDezIebX6DOlX4gX15ktm5MX+T+C2YV9VJkPGZK14GJTysU9LRnn32J ObEv/ZyZEDfKWMwuGKKj89m15Hej6Omua7kLPxzhG7pKulqXE8e8d8VFNZFIwkC0yTCL bh0rp65BZFZs9GVTBBkMIWYbCCwhGEJ5aGFAZN1ZBU+p4W91v57HJhCl2fs8GhijBpC/ yEF8s8CVJC79eJc1HlZ1PdiZ2YSwj12gRWG+wiEHuTxDmQVdZw6rdxvnURqPPAd1JFgH 7QzJM+zRjZ1KjO0nmutWZDxkLHFsI6o55x3NlMjfNtPhnG49ruf2SrtoTAiE0eI4c0K+ SNlg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=fxcLkCiIJRwl4RWn8+1v7sT5YlgbZRj3mI8Z1w4zYhI=; b=AeWoNAHXGdXgT5FtW2Z7BcMxDbsGXPjfAJspD+zHRn6udMMiFwrWYXEdiIFsUfqdJv jTLzq66IqZAHClF7bkMM5waVUsS00JOIGxVuJfcK/XU8wdGNXt/2rzXfnedDJKMy+5Zf 5UIqrcNZDDCz+bnL8ebFhbudXT4c3EoPLcWvKNhaXNfTLKNocqnpRp789jTNRwnJstZh VpTY5IvVfyR02ODe/XtP7KyRRpmdmQu0u16UZrgLqmXwdRyE0k/v2nbvdijQpmkOGXZ4 g2gL/VoGhKF9focGiRuo3wr+7KDzYPI/qktfTRGD81kd06KjT5zpeHggzOlsNpKdV657 FFmQ== X-Gm-Message-State: APjAAAXgSlCkHes4c2AGUKhQAhovdBiu+vYRi9pXTFI5K8jTGaLvpGf8 YwGPC/PvnHKuwE8GokWOIElXJ1KO X-Google-Smtp-Source: APXvYqxJ6BOBhjIQLeUVMvokuzmxFhEBawroaSrhOzifQf3nsuUfuNwA6QUSFh4GLrFewT1oqhvZRg== X-Received: by 2002:a63:3148:: with SMTP id x69mr2528088pgx.300.1566986055355; Wed, 28 Aug 2019 02:54:15 -0700 (PDT) Received: from localhost.localdomain ([39.117.32.11]) by smtp.gmail.com with ESMTPSA id m13sm2101432pgn.57.2019.08.28.02.54.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 28 Aug 2019 02:54:14 -0700 (PDT) From: Jongpil Jung To: linux-input@vger.kernel.org Cc: Jongpil Jung Subject: [PATCH 4/8] Input: atmel_mxt_ts - add interface to read ts sensor matrix info. Date: Wed, 28 Aug 2019 18:53:45 +0900 Message-Id: <20190828095349.30607-4-jongpuls@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190828095349.30607-1-jongpuls@gmail.com> References: <20190828095349.30607-1-jongpuls@gmail.com> Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org From: Jongpil Jung To get more hardware information, make interface to read sensor matrix size. Change-Id: I41a72b4c4031f2041479f183b59162da3281beda --- drivers/input/touchscreen/atmel_mxt_ts.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index cb3a608f60bf..f5eb81ff2fd3 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -2743,6 +2743,16 @@ static ssize_t mxt_info_csum_show(struct device *dev, return scnprintf(buf, PAGE_SIZE, "%06x\n", data->info_crc); } +/* Matrix Size is */ +static ssize_t mxt_matrix_size_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mxt_data *data = dev_get_drvdata(dev); + struct mxt_info *info = data->info; + return scnprintf(buf, PAGE_SIZE, "%u %u\n", + info->matrix_xsize, info->matrix_ysize); +} + static ssize_t mxt_show_instance(char *buf, int count, struct mxt_object *object, int instance, const u8 *val) @@ -2976,6 +2986,7 @@ static DEVICE_ATTR(config_csum, S_IRUGO, mxt_config_csum_show, NULL); static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL); static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL); static DEVICE_ATTR(info_csum, S_IRUGO, mxt_info_csum_show, NULL); +static DEVICE_ATTR(matrix_size, S_IRUGO, mxt_matrix_size_show, NULL); static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL); static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store); @@ -2986,6 +2997,7 @@ static struct attribute *mxt_attrs[] = { &dev_attr_fw_version.attr, &dev_attr_hw_version.attr, &dev_attr_info_csum.attr, + &dev_attr_matrix_size.attr, &dev_attr_object.attr, &dev_attr_update_fw.attr, NULL From patchwork Wed Aug 28 09:53:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jongpil Jung X-Patchwork-Id: 11118427 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D06DE184E for ; Wed, 28 Aug 2019 09:54:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A6A6E2054F for ; Wed, 28 Aug 2019 09:54:19 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="dtIAzGL+" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726370AbfH1JyT (ORCPT ); Wed, 28 Aug 2019 05:54:19 -0400 Received: from mail-pg1-f194.google.com ([209.85.215.194]:42047 "EHLO mail-pg1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726368AbfH1JyT (ORCPT ); Wed, 28 Aug 2019 05:54:19 -0400 Received: by mail-pg1-f194.google.com with SMTP id p3so1174465pgb.9 for ; Wed, 28 Aug 2019 02:54:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=37vNt0MkG6rl24DSa2HEQH3ZUDhUE6wULD9x6UvkMLc=; b=dtIAzGL+Q5upU5zh7YTyJ/yn7U+n8fmhqS+ubv/Nzt/6pLuwBY71zmRJdTySt85gNm i0dYhgRd10LiX6fHdx+if2PU5hT4WO7UJ5TnubsgUXFOieGjZXSoc5bLpS8hlv/wJ95T 3cWFsgDktbADTDEtHcKGLdJ8UQ8HGWzgFF+AcueKplqlN3V1wSgNUGwIAj5740MpVoc5 e2yV4lFmHb80RdUe7dh+cs3RfmSqU+RHeiR6SdHVlKwWQWqk57OsAp+XpM37WGSM6M97 hlnUz+LnR1k1XJFd8y1BJh2yxV8ovoR4j4GlWtRhmXk3HDt+n/rx2ZZJARQ3pVIceuOi k81Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=37vNt0MkG6rl24DSa2HEQH3ZUDhUE6wULD9x6UvkMLc=; b=pbNCKjvyptvvmL/16+KOFVijOLCWUfwMeEB1bg2X9ifjcSIgdB9Y04JKIDIorIM8lp kAU1taxtj5mR99+d0vKDmMZWZnrJTEM4mQQa2HGdgxULpd7r77nJU/nJvc9Em+o/ILPw gz5ug/VxjvZ4/RPwH5EvZVRim1E+akNMPod++u3c6zohrZHO91JzPGM/4JCYLVEad6pK u/9n/tJ6vd4lhPkNvMeb2QU0QqKYd+iVqheihqbb1bjitDiWIvTph316JsXnx6Ru4o5z XgjKkyoB6x42n8I+eXAQq2bpyksH7RVi70LsINtcamFzwTiuDsk18b67WNJdfgm9Znbh PjZg== X-Gm-Message-State: APjAAAWgXbSiBPse7f4NnE933hBzGOIYqOdZ8/onuVLpQcAJLo4ncZPW msyS/t2LxvZGp6+7QYPOn7n1jcqt X-Google-Smtp-Source: APXvYqw/mCVJYMfg6NRXVZSoxY99rgTnFiLFCxLA3FPREZUmGNHDVUB2Ad/UvAbBBNPKCY9NcmN2Ww== X-Received: by 2002:aa7:93cf:: with SMTP id y15mr3577924pff.251.1566986057905; Wed, 28 Aug 2019 02:54:17 -0700 (PDT) Received: from localhost.localdomain ([39.117.32.11]) by smtp.gmail.com with ESMTPSA id m13sm2101432pgn.57.2019.08.28.02.54.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 28 Aug 2019 02:54:17 -0700 (PDT) From: Jongpil Jung To: linux-input@vger.kernel.org Cc: Jongpil Jung Subject: [PATCH 5/8] Input: atmel_mxt_ts - store mxt_info into structure instead of pointer. Date: Wed, 28 Aug 2019 18:53:46 +0900 Message-Id: <20190828095349.30607-5-jongpuls@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190828095349.30607-1-jongpuls@gmail.com> References: <20190828095349.30607-1-jongpuls@gmail.com> Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org From: Jongpil Jung To maintain mxt_info easiler, use structure type mxt_info instead of pointer. Change-Id: I89f19a45b395a071d2ea01efa1d80f15fc3ed461 --- drivers/input/touchscreen/atmel_mxt_ts.c | 35 ++++++++++++------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index f5eb81ff2fd3..723ff75e798a 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -281,7 +281,7 @@ struct mxt_data { struct input_dev *input_dev; char phys[64]; /* device physical location */ struct mxt_object *object_table; - struct mxt_info *info; + struct mxt_info info; void *raw_info_block; unsigned int irq; unsigned int max_x; @@ -464,7 +464,7 @@ static int mxt_lookup_bootloader_address(struct mxt_data *data, bool retry) { u8 appmode = data->client->addr; u8 bootloader; - u8 family_id = data->info ? data->info->family_id : 0; + u8 family_id = data->info.family_id; switch (appmode) { case 0x4a: @@ -697,7 +697,7 @@ mxt_get_object(struct mxt_data *data, u8 type) struct mxt_object *object; int i; - for (i = 0; i < data->info->object_num; i++) { + for (i = 0; i < data->info.object_num; i++) { object = data->object_table + i; if (object->type == type) return object; @@ -1486,13 +1486,13 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw) cfg.raw_pos += offset; } - if (cfg.info.family_id != data->info->family_id) { + if (cfg.info.family_id != data->info.family_id) { dev_err(dev, "Family ID mismatch!\n"); ret = -EINVAL; goto release_raw; } - if (cfg.info.variant_id != data->info->variant_id) { + if (cfg.info.variant_id != data->info.variant_id) { dev_err(dev, "Variant ID mismatch!\n"); ret = -EINVAL; goto release_raw; @@ -1541,7 +1541,7 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw) /* Malloc memory to store configuration */ cfg.start_ofs = MXT_OBJECT_START + - data->info->object_num * sizeof(struct mxt_object) + + data->info.object_num * sizeof(struct mxt_object) + MXT_INFO_CHECKSUM_SIZE; cfg.mem_size = data->mem_size - cfg.start_ofs; cfg.mem = kzalloc(cfg.mem_size, GFP_KERNEL); @@ -1609,7 +1609,6 @@ static void mxt_free_object_table(struct mxt_data *data) v4l2_device_unregister(&data->dbg.v4l2); #endif data->object_table = NULL; - data->info = NULL; kfree(data->raw_info_block); data->raw_info_block = NULL; kfree(data->msg_buf); @@ -1639,7 +1638,7 @@ static int mxt_parse_object_table(struct mxt_data *data, /* Valid Report IDs start counting from 1 */ reportid = 1; data->mem_size = 0; - for (i = 0; i < data->info->object_num; i++) { + for (i = 0; i < data->info.object_num; i++) { struct mxt_object *object = object_table + i; u8 min_id, max_id; @@ -1663,8 +1662,8 @@ static int mxt_parse_object_table(struct mxt_data *data, switch (object->type) { case MXT_GEN_MESSAGE_T5: - if (data->info->family_id == 0x80 && - data->info->version < 0x20) { + if (data->info.family_id == 0x80 && + data->info.version < 0x20) { /* * On mXT224 firmware versions prior to V2.0 * read and discard unused CRC byte otherwise @@ -1797,13 +1796,13 @@ static int mxt_read_info_block(struct mxt_data *data) } data->raw_info_block = id_buf; - data->info = (struct mxt_info *)id_buf; + memcpy(&data->info, id_buf, sizeof(struct mxt_info)); dev_info(&client->dev, "Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n", - data->info->family_id, data->info->variant_id, - data->info->version >> 4, data->info->version & 0xf, - data->info->build, data->info->object_num); + data->info.family_id, data->info.variant_id, + data->info.version >> 4, data->info.version & 0xf, + data->info.build, data->info.object_num); /* Parse object table information */ error = mxt_parse_object_table(data, id_buf + MXT_OBJECT_START); @@ -2721,7 +2720,7 @@ static ssize_t mxt_fw_version_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mxt_data *data = dev_get_drvdata(dev); - struct mxt_info *info = data->info; + struct mxt_info *info = &data->info; return scnprintf(buf, PAGE_SIZE, "%u.%u.%02X\n", info->version >> 4, info->version & 0xf, info->build); } @@ -2731,7 +2730,7 @@ static ssize_t mxt_hw_version_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mxt_data *data = dev_get_drvdata(dev); - struct mxt_info *info = data->info; + struct mxt_info *info = &data->info; return scnprintf(buf, PAGE_SIZE, "%u.%u\n", info->family_id, info->variant_id); } @@ -2748,7 +2747,7 @@ static ssize_t mxt_matrix_size_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mxt_data *data = dev_get_drvdata(dev); - struct mxt_info *info = data->info; + struct mxt_info *info = &data->info; return scnprintf(buf, PAGE_SIZE, "%u %u\n", info->matrix_xsize, info->matrix_ysize); } @@ -2787,7 +2786,7 @@ static ssize_t mxt_object_show(struct device *dev, return -ENOMEM; error = 0; - for (i = 0; i < data->info->object_num; i++) { + for (i = 0; i < data->info.object_num; i++) { object = data->object_table + i; if (!mxt_object_readable(object->type)) From patchwork Wed Aug 28 09:53:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jongpil Jung X-Patchwork-Id: 11118429 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D6AB214F7 for ; Wed, 28 Aug 2019 09:54:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B5CC92054F for ; Wed, 28 Aug 2019 09:54:21 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="CZi2n7W7" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726273AbfH1JyV (ORCPT ); Wed, 28 Aug 2019 05:54:21 -0400 Received: from mail-pl1-f174.google.com ([209.85.214.174]:45663 "EHLO mail-pl1-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726368AbfH1JyV (ORCPT ); Wed, 28 Aug 2019 05:54:21 -0400 Received: by mail-pl1-f174.google.com with SMTP id y8so988243plr.12 for ; Wed, 28 Aug 2019 02:54:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=UQnwzKcveqCmOUaA3/3c8b6J5UefneOvlIC1zJw4bkw=; b=CZi2n7W77Z0A7UyWNTMUBJtOH8WJK7Ggqtowll+q3WUbEImB7ARxf5S2RU1880C8Vn F22+VNw0MEfFNkSWeUg1mwlvkYRchzdZT5dZFlbQajBH2oL8Z3kqCDr3Nx69K72daNuO uG5pzY7geX6lIYrWLClTXk0WBMG1aCCD1ih1XNOf/N6loFYc19fUjn5vhejcPBrfYN/g iKTSYyr5psTjy7kH74iqFCQm44fbhfX0Di4ViQ0kamAtFAG+8/wpsRTKwg7yJf9cFsmt h4ZGJBLu8Qu58qzWMIEtqTBVK4Yv9N4iD0Lv8I1p5TYO9YMAymVnooT4J8exMG9Sow0o ISYg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=UQnwzKcveqCmOUaA3/3c8b6J5UefneOvlIC1zJw4bkw=; b=BZ35WPEcPDiL7rBQB0u7qPVsCs1eonmK5q6MFhgb7wIvPzJ/N4uscRWxNIQWW6phUB B4Cn2rCImmoNX9A7YKeyqjBdnv2ahvOwuj9tJUfEEIS4snLKqzELnVHQFk3ivuMbnZlz 631w8eyJkvK+Aq1f4HNYURk/AiHTGHHgxKNS7cZdl5YUDrIrX9c+0FmxvZSV9K45nCXa fK3pHmjdExaux+eCheK1t7UCIUC41wupOh2TgBHUXd/naUdV2Z/AOPLG/NTe7Md1FWNk 80k1BkiWPsvV+UDKsUz4bTpC6U+n0bJdOfIH7HK7BRYjgilq6ZplPxbmWO4/yJY95a4Z L3Qw== X-Gm-Message-State: APjAAAWCL3Us6YHfl1zm/CoYAdsSYgI35azPNkBl+Uka4K3ooXGG/bIM ZC5g4ieMg1VswNDAGwk4D3lfIoEU X-Google-Smtp-Source: APXvYqzo6NwiDSB73LYa79Qw5+Gu0rESWTZU38nCxLV73kFUc8a4keCtjl5+K+ciUkA6mjkGA6/xjw== X-Received: by 2002:a17:902:3064:: with SMTP id u91mr3485177plb.244.1566986060286; Wed, 28 Aug 2019 02:54:20 -0700 (PDT) Received: from localhost.localdomain ([39.117.32.11]) by smtp.gmail.com with ESMTPSA id m13sm2101432pgn.57.2019.08.28.02.54.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 28 Aug 2019 02:54:19 -0700 (PDT) From: Jongpil Jung To: linux-input@vger.kernel.org Cc: Jongpil Jung Subject: [PATCH 6/8] Input: atmel_mxt_ts - add active to idle timeout in T7. Date: Wed, 28 Aug 2019 18:53:47 +0900 Message-Id: <20190828095349.30607-6-jongpuls@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190828095349.30607-1-jongpuls@gmail.com> References: <20190828095349.30607-1-jongpuls@gmail.com> Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org From: Jongpil Jung T7 has active to idle timeout information. Add active to idle timeout information into structure so that we can refer information easily. Change-Id: Ie4682cff3d3bb1b8b537702656862eb34f64a0b8 --- drivers/input/touchscreen/atmel_mxt_ts.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 723ff75e798a..3a17adf04e2a 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -94,6 +94,7 @@ struct t7_config { u8 idle; u8 active; + u8 activetoidleto; } __packed; #define MXT_POWER_CFG_RUN 0 @@ -2176,6 +2177,8 @@ static int mxt_set_t7_power_cfg(struct mxt_data *data, u8 sleep) struct t7_config *new_config; struct t7_config deepsleep = { .active = 0, .idle = 0 }; + deepsleep.activetoidleto = data->t7_cfg.activetoidleto; + if (sleep == MXT_POWER_CFG_DEEPSLEEP) new_config = &deepsleep; else @@ -2186,8 +2189,8 @@ static int mxt_set_t7_power_cfg(struct mxt_data *data, u8 sleep) if (error) return error; - dev_dbg(dev, "Set T7 ACTV:%d IDLE:%d\n", - new_config->active, new_config->idle); + dev_dbg(dev, "Set T7 ACTV:%d IDLE:%d ACTV2IDLETO:%d\n", + new_config->active, new_config->idle, new_config->activetoidleto); return 0; } @@ -2218,8 +2221,8 @@ static int mxt_init_t7_power_cfg(struct mxt_data *data) } } - dev_dbg(dev, "Initialized power cfg: ACTV %d, IDLE %d\n", - data->t7_cfg.active, data->t7_cfg.idle); + dev_dbg(dev, "Initialized power cfg: ACTV %d, IDLE %d, ACTV2IDLETO:%d\n", + data->t7_cfg.active, data->t7_cfg.idle, data->t7_cfg.activetoidleto); return 0; } From patchwork Wed Aug 28 09:53:48 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jongpil Jung X-Patchwork-Id: 11118431 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C9A82184E for ; Wed, 28 Aug 2019 09:54:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A053A2054F for ; Wed, 28 Aug 2019 09:54:24 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="oLVaBKho" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726378AbfH1JyY (ORCPT ); Wed, 28 Aug 2019 05:54:24 -0400 Received: from mail-pf1-f196.google.com ([209.85.210.196]:36213 "EHLO mail-pf1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726368AbfH1JyY (ORCPT ); Wed, 28 Aug 2019 05:54:24 -0400 Received: by mail-pf1-f196.google.com with SMTP id w2so1391610pfi.3 for ; Wed, 28 Aug 2019 02:54:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=H99pz8hJRALi07IvORKmej1UWm69GcBOFPDW+oTWEQY=; b=oLVaBKho4x17A6fx60576uVdEm5Ec6Kur4sF1rCZKP5Vd3vXKq/j1IQ2Q3C5gShSQP Q7UrT6WeHpCrA0Z/WVintWhHyxCXNbh7mm325T8HgsxJ1vlmckQ1opw5S45U6dWmOuc5 Bd2giiqx4x6iAF2Db7EPo+9fFTQTqZPDeUVcNbeskfESqZC1sIo0fQ4JfrIFh7Kil0K4 WjUy29wR4Lab3ZZQWnPVOix/vm0w+THsGEUXR6p0WuRhNNd1iywQhq6wLfcXBSbZO5+4 itbp7U4A6PTvGeA8vDUJs1MLRimJ/0Sw0z4qa+4a7m7cDMfT2gkmJUk1cbXioAjlO911 SQSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=H99pz8hJRALi07IvORKmej1UWm69GcBOFPDW+oTWEQY=; b=KF8vLMn67EXO5eyZespnznirVay7KzxgbY7AMgB0jWhmL6y/M2ZJsWedVHv9mSADMV 8EF856L+rR7Gzi5eDhx8TO9tdwjC12ymOdbLTIZ3jQ9jy93hnkIh8DHSKjoq8S+561XA ixuQ9Ej5EiIOO5slB3xt2lGTfk/ZIlWSWtDFlP9KbegOsvIEcsmcjhXXTA0bfb17Flmy r0AKDT5vibKoVKbTav6V/RD04TyXaqulctYVGfT97mU/osVSL+fzmjYfo0Aru6EpE5Wb BZS0ItZmaEIfMOpOLk1pbD6sj+m4JHnCLmrXsYgfE6MsdJG4q3ltUtuL7LEYYV6dQSkl 1eCQ== X-Gm-Message-State: APjAAAUw3Bda27369KSHy1gIFqkLS0lhagnUcs+O5eSGf1PuDzKc8zFQ afOBN+ELEGOm9MaPd5rlesgBDiMG X-Google-Smtp-Source: APXvYqx/Y4cB/YDSKkkyAng422qFflMduovsBqEuBIjK0wigs8+fhOXRVApogqbciSvoiqOklJdvpg== X-Received: by 2002:a17:90a:22c9:: with SMTP id s67mr3384299pjc.22.1566986062607; Wed, 28 Aug 2019 02:54:22 -0700 (PDT) Received: from localhost.localdomain ([39.117.32.11]) by smtp.gmail.com with ESMTPSA id m13sm2101432pgn.57.2019.08.28.02.54.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 28 Aug 2019 02:54:22 -0700 (PDT) From: Jongpil Jung To: linux-input@vger.kernel.org Cc: Jongpil Jung Subject: [PATCH 7/8] Input: atmel_mxt_ts - add interface to read/write config file name. Date: Wed, 28 Aug 2019 18:53:48 +0900 Message-Id: <20190828095349.30607-7-jongpuls@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190828095349.30607-1-jongpuls@gmail.com> References: <20190828095349.30607-1-jongpuls@gmail.com> Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org From: Jongpil Jung Add interface to change config/firmware file name easily. So, we can pass file name to kernel space before we update config/firmware. Change-Id: I5b0253feb47e62d7013148f5ef117a9f2ba0b162 --- drivers/input/touchscreen/atmel_mxt_ts.c | 97 ++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 3a17adf04e2a..2f1013c97433 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -334,6 +334,12 @@ struct mxt_data { /* for config update handling */ struct completion crc_completion; + /* firmware file name */ + char *fw_file; + + /* config file name */ + char *config_file; + u32 *t19_keymap; unsigned int t19_num_keys; @@ -2681,6 +2687,42 @@ static int mxt_configure_objects(struct mxt_data *data, return 0; } +static int mxt_update_file_name(struct device *dev, char **file_name, + const char *buf, size_t count) +{ + char *new_file_name; + + /* Simple sanity check */ + if (count > 64) { + dev_warn(dev, "File name too long\n"); + return -EINVAL; + } + + /* FIXME: devm_kmemdup() when available */ + new_file_name = devm_kmalloc(dev, count + 1, GFP_KERNEL); + if (!new_file_name) { + dev_warn(dev, "no memory\n"); + return -ENOMEM; + } + + memcpy(new_file_name, buf, count + 1); + + dev_dbg(dev, "new file name %s\n", new_file_name); + + /* Echo into the sysfs entry may append newline at the end of buf */ + if (new_file_name[count - 1] == '\n') + count--; + + new_file_name[count] = '\0'; + + if (*file_name) + devm_kfree(dev, *file_name); + + *file_name = new_file_name; + + return 0; +} + static ssize_t mxt_backupnv_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -2718,6 +2760,45 @@ static ssize_t mxt_config_csum_show(struct device *dev, return scnprintf(buf, PAGE_SIZE, "%06x\n", data->config_crc); } +static ssize_t mxt_config_file_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mxt_data *data = dev_get_drvdata(dev); + return scnprintf(buf, PAGE_SIZE, "%s\n", data->config_file); +} + +static ssize_t mxt_config_file_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct mxt_data *data = dev_get_drvdata(dev); + int ret; + + ret = mxt_update_file_name(dev, &data->config_file, buf, count); + return ret ? ret : count; +} + +static ssize_t mxt_fw_file_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mxt_data *data = dev_get_drvdata(dev); + return scnprintf(buf, PAGE_SIZE, "%s\n", data->fw_file); +} + +static ssize_t mxt_fw_file_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct mxt_data *data = dev_get_drvdata(dev); + int ret; + + ret = mxt_update_file_name(dev, &data->fw_file, buf, count); + if (ret) + return ret; + + return count; +} + /* Firmware Version is returned as Major.Minor.Build */ static ssize_t mxt_fw_version_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -2985,6 +3066,10 @@ static ssize_t mxt_update_fw_store(struct device *dev, static DEVICE_ATTR(backupnv, S_IWUSR, NULL, mxt_backupnv_store); static DEVICE_ATTR(calibrate, S_IWUSR, NULL, mxt_calibrate_store); static DEVICE_ATTR(config_csum, S_IRUGO, mxt_config_csum_show, NULL); +static DEVICE_ATTR(config_file, S_IRUGO | S_IWUSR, mxt_config_file_show, + mxt_config_file_store); +static DEVICE_ATTR(fw_file, S_IRUGO | S_IWUSR, mxt_fw_file_show, + mxt_fw_file_store); static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL); static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL); static DEVICE_ATTR(info_csum, S_IRUGO, mxt_info_csum_show, NULL); @@ -2996,6 +3081,8 @@ static struct attribute *mxt_attrs[] = { &dev_attr_backupnv.attr, &dev_attr_calibrate.attr, &dev_attr_config_csum.attr, + &dev_attr_config_file.attr, + &dev_attr_fw_file.attr, &dev_attr_fw_version.attr, &dev_attr_hw_version.attr, &dev_attr_info_csum.attr, @@ -3167,6 +3254,16 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) if (error) return error; + error = mxt_update_file_name(&client->dev, &data->fw_file, MXT_FW_NAME, + strlen(MXT_FW_NAME)); + if (error) + return error; + + error = mxt_update_file_name(&client->dev, &data->config_file, + MXT_CFG_NAME, strlen(MXT_CFG_NAME)); + if (error) + return error; + data->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(data->reset_gpio)) { From patchwork Wed Aug 28 09:53:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jongpil Jung X-Patchwork-Id: 11118433 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CBF9E184E for ; Wed, 28 Aug 2019 09:54:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8F1EB217F5 for ; Wed, 28 Aug 2019 09:54:27 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="MiQlSO7l" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726382AbfH1Jy1 (ORCPT ); Wed, 28 Aug 2019 05:54:27 -0400 Received: from mail-pg1-f196.google.com ([209.85.215.196]:46175 "EHLO mail-pg1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726368AbfH1Jy0 (ORCPT ); Wed, 28 Aug 2019 05:54:26 -0400 Received: by mail-pg1-f196.google.com with SMTP id m3so1164078pgv.13 for ; Wed, 28 Aug 2019 02:54:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=SKZjvO1p102FADuTX50l2VuWSq7lWEumYWEfsQxT1MQ=; b=MiQlSO7lao32QTiFjAcD7dVZLnhBypomjDBPGJojU+hTc1rPQNpKivnNyuKGvngyx3 UxE8FbtBStZ+rbOs2Wod+MrYEL7TOXi3OKcLL0IkQy0Qi5mBTeQlAzn7QlaSnbixoBDb ALuQtZ+D/D9GMOB07olNe71REZFlxtict0BvgELHooJWTaGHiO/kIOq7eTMeDtj4bSwd g0Y2tt6xs/W+36JDrOZtaPFJ2+JCKsIDF36UzOb+8d/ba+3zh6jmhDyAuv6yUHk5fcvU u78DfMoz0t+/vVoUP0ZPj+q6MkQP8mVYBaYUwoaZil86thrYUUTogsNKC7TRiv4etNhw TWFA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=SKZjvO1p102FADuTX50l2VuWSq7lWEumYWEfsQxT1MQ=; b=giUGGjeW40Q19GHcX4ZGq7YYzDC49UukNMt7tF1I3hvKo6ZN+CzBWvjMP+LZQDxy0g ZMsrVmGHyu6IXQxtREWDwDxhZlLdNYCR9clQuCPEgU8yRcISYeRrWbm8Qus1hvB3HgfB 5YgKIpw8FyysHcNPKjJO1iIqCcw9IT0jasxvyGzRwNU6B2U9SS6L+S5kwVnlHHHGP1+G cFi9RvAgK8iG0lSnpVAoeVYsmjRsPaVz55HJ4rwHxeZUboE7upxybhJBQjA1qLSHzJW6 LmobKXWMyYanbk6SvyLFD7f2ucQ8eeD2XLdpHdLAyLu15XQtIYTtkWTiPQRDh0L2RJ6D yolw== X-Gm-Message-State: APjAAAX7G9IuMqvZ0htGb94BrxEmFpAsdGrSbFVBBlrT5t5OEHp349N1 9i7gWVb8/FaloQhMoSVgGOUz9gY6 X-Google-Smtp-Source: APXvYqzNuYXvwDFQrjinihtwOYO5sSbfrwMejXTO3MZUCUHvbJdOoWkvNhaLe1u/YsVNPSmQw/9yeg== X-Received: by 2002:a63:6106:: with SMTP id v6mr2693793pgb.36.1566986065061; Wed, 28 Aug 2019 02:54:25 -0700 (PDT) Received: from localhost.localdomain ([39.117.32.11]) by smtp.gmail.com with ESMTPSA id m13sm2101432pgn.57.2019.08.28.02.54.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 28 Aug 2019 02:54:24 -0700 (PDT) From: Jongpil Jung To: linux-input@vger.kernel.org Cc: Jongpil Jung Subject: [PATCH 8/8] Input: atmel_mxt_ts - enable config update from user space. Date: Wed, 28 Aug 2019 18:53:49 +0900 Message-Id: <20190828095349.30607-8-jongpuls@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190828095349.30607-1-jongpuls@gmail.com> References: <20190828095349.30607-1-jongpuls@gmail.com> Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org From: Jongpil Jung Enable config update for atmel mxt touchscreen ic. Here is config update step. 1. load config file from file system. If you want to use different config file, you may update config file name. 2. Make ic uninterruptable before you update config. 3. Load config and verify header inforamtion. 4. Write config into IC. 5. Backup IC register data into backup nvram. 6. Reset device. 7. Save power config and register into device driver data. Change-Id: Ied53bff486d04133602761efc5e9ea933e4f741e --- drivers/input/touchscreen/atmel_mxt_ts.c | 678 ++++++++++++++++++++++- 1 file changed, 673 insertions(+), 5 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 2f1013c97433..09bcaf49abfb 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -70,6 +70,7 @@ #define MXT_SPT_MESSAGECOUNT_T44 44 #define MXT_SPT_CTECONFIG_T46 46 #define MXT_SPT_DYNAMICCONFIGURATIONCONTAINER_T71 71 +#define MXT_SPT_TOUCHSCREENHOVER_T101 101 #define MXT_TOUCH_MULTITOUCHSCREEN_T100 100 /* MXT_GEN_MESSAGE_T5 object */ @@ -105,7 +106,7 @@ struct t7_config { #define MXT_T9_XSIZE 3 #define MXT_T9_YSIZE 4 #define MXT_T9_ORIENT 9 -#define MXT_T9_RANGE 18 +#define MXT_T9_XRANGE_LSB 18 /* MXT_TOUCH_MULTI_T9 status */ #define MXT_T9_UNGRIP BIT(0) @@ -157,19 +158,27 @@ struct t37_debug { /* T100 Multiple Touch Touchscreen */ #define MXT_T100_CTRL 0 #define MXT_T100_CFG1 1 -#define MXT_T100_TCHAUX 3 +#define MXT_T100_SCRAUX 2 +#define MXT_T100_TCHAUX 3 #define MXT_T100_XSIZE 9 -#define MXT_T100_XRANGE 13 +#define MXT_T100_XRANGE 13 #define MXT_T100_YSIZE 20 -#define MXT_T100_YRANGE 24 +#define MXT_T100_YRANGE 24 #define MXT_T100_CFG_SWITCHXY BIT(5) + +#define MXT_T100_SRCAUX_NUMRPTTCH BIT(0) +#define MXT_T100_SRCAUX_TCHAREA BIT(1) +#define MXT_T100_SRCAUX_ATCHAREA BIT(2) +#define MXT_T100_SRCAUX_INTTHRAREA BIT(3) + #define MXT_T100_CFG_INVERTY BIT(6) #define MXT_T100_CFG_INVERTX BIT(7) #define MXT_T100_TCHAUX_VECT BIT(0) #define MXT_T100_TCHAUX_AMPL BIT(1) #define MXT_T100_TCHAUX_AREA BIT(2) +#define MXT_T100_TCHAUX_PEAK BIT(4) #define MXT_T100_DETECT BIT(7) #define MXT_T100_TYPE_MASK 0x70 @@ -214,11 +223,21 @@ enum t100_type { #define MXT_BOOT_EXTENDED_ID BIT(5) #define MXT_BOOT_ID_MASK 0x1f +/* Touch orient bits */ +#define MXT_XY_SWITCH (1 << 0) + /* Touchscreen absolute values */ #define MXT_MAX_AREA 0xff #define MXT_PIXELS_PER_MM 20 +struct mxt_cfg_file_line { + struct list_head list; + u16 addr; + u8 size; + u8 *content; +}; + struct mxt_info { u8 family_id; u8 variant_id; @@ -287,6 +306,10 @@ struct mxt_data { unsigned int irq; unsigned int max_x; unsigned int max_y; + + /* max touchscreen area in terms of pixels and channels */ + unsigned int max_area_pixels; + unsigned int max_area_channels; bool invertx; bool inverty; bool xy_switch; @@ -300,6 +323,10 @@ struct mxt_data { u8 max_reportid; u32 config_crc; u32 info_crc; + + bool has_T9; + bool has_T100; + u8 bootloader_addr; u8 *msg_buf; u8 t6_status; @@ -308,6 +335,21 @@ struct mxt_data { u8 num_touchids; u8 multitouch; struct t7_config t7_cfg; + bool t7_cfg_valid; + + u8 T101_ctrl; + bool T101_ctrl_valid; + + /* Saved T42 Touch Suppression field */ + u8 T42_ctrl; + bool T42_ctrl_valid; + + /* Saved T19 GPIO config */ + u8 T19_ctrl; + bool T19_ctrl_valid; + + u8 T19_status; + struct mxt_dbg dbg; struct gpio_desc *reset_gpio; @@ -325,6 +367,16 @@ struct mxt_data { u8 T100_reportid_min; u8 T100_reportid_max; + /* T100 Configuration. Which calculations are enabled*/ + bool T100_enabled_num_reportable_touches; + bool T100_enabled_touch_area; + bool T100_enabled_antitouch_area; + bool T100_enabled_internal_tracking_area; + bool T100_enabled_vector; + bool T100_enabled_amplitude; + bool T100_enabled_area; + bool T100_enabled_peak; + /* for fw update in bootloader */ struct completion bl_completion; @@ -334,6 +386,12 @@ struct mxt_data { /* for config update handling */ struct completion crc_completion; + /* + * Protects from concurrent firmware/config updates and + * suspending/resuming. + */ + struct mutex fw_mutex; + /* firmware file name */ char *fw_file; @@ -351,6 +409,15 @@ struct mxt_vb2_buffer { struct list_head list; }; +/* Define Global Functions in here */ +static int mxt_calc_resolution_T9(struct mxt_data *data); +static int mxt_calc_resolution_T100(struct mxt_data *data); +static void mxt_save_power_config(struct mxt_data *data); +static void mxt_save_aux_regs(struct mxt_data *data); +static void mxt_start(struct mxt_data *data); +static void mxt_stop(struct mxt_data *data); +static int mxt_get_config_from_chip(struct mxt_data *data); + static size_t mxt_obj_size(const struct mxt_object *obj) { return obj->size_minus_one + 1; @@ -396,6 +463,14 @@ static bool mxt_object_readable(unsigned int type) } } +static inline bool is_hovering_supported(struct mxt_data *data) +{ + struct mxt_info *info = &data->info; + /* vairant_id: 337t(164.17), 2954t2(164.13) */ + return ((info->family_id == 164) && + ((info->variant_id == 13) || (info->variant_id == 17))); +} + static void mxt_dump_message(struct mxt_data *data, u8 *message) { dev_dbg(&data->client->dev, "message: %*ph\n", @@ -1853,7 +1928,7 @@ static int mxt_read_t9_resolution(struct mxt_data *data) return error; error = __mxt_read_reg(client, - object->start_address + MXT_T9_RANGE, + object->start_address + MXT_T9_XRANGE_LSB, sizeof(range), &range); if (error) return error; @@ -2687,6 +2762,547 @@ static int mxt_configure_objects(struct mxt_data *data, return 0; } +static int mxt_save_regs(struct mxt_data *data, u8 type, u8 instance, + u8 offset, u8 *val, u16 size) +{ + struct mxt_object *object; + u16 addr; + int ret; + + object = mxt_get_object(data, type); + if (!object) + return -EINVAL; + + addr = object->start_address + instance * mxt_obj_size(object) + offset; + ret = __mxt_read_reg(data->client, addr, size, val); + if (ret) + return -EINVAL; + + return 0; +} + +static void mxt_save_power_config(struct mxt_data *data) +{ + struct device *dev = &data->client->dev; + int ret; + + /* Save 3 bytes T7 Power config */ + ret = mxt_save_regs(data, MXT_GEN_POWER_T7, 0, 0, + (u8 *)&data->t7_cfg, sizeof(struct t7_config)); + if (ret) + dev_err(dev, "Save T7 Power config failed, %d\n", ret); + + data->t7_cfg_valid = (ret == 0); +} + +static void mxt_save_aux_regs(struct mxt_data *data) +{ + struct device *dev = &data->client->dev; + int ret; + + if (is_hovering_supported(data)) { + /* Save 1 byte T101 Ctrl config */ + ret = mxt_save_regs(data, MXT_SPT_TOUCHSCREENHOVER_T101, 0, 0, + &data->T101_ctrl, 1); + if (ret) + dev_err(dev, "Save T101 ctrl config failed, %d\n", ret); + data->T101_ctrl_valid = (ret == 0); + } + + ret = mxt_save_regs(data, MXT_PROCI_TOUCHSUPPRESSION_T42, 0, 0, + &data->T42_ctrl, 1); + if (ret) + dev_err(dev, "Save T42 ctrl config failed, %d\n", ret); + data->T42_ctrl_valid = (ret == 0); + + ret = mxt_save_regs(data, MXT_SPT_GPIOPWM_T19, 0, 0, + &data->T19_ctrl, 1); + if (ret) + dev_err(dev, "Save T19 ctrl config failed, %d\n", ret); + data->T19_ctrl_valid = (ret == 0); +} + +static int mxt_update_setting_T100(struct mxt_data *data) +{ + struct i2c_client *client = data->client; + struct mxt_object *T100; + u8 srcaux, tchaux; + int ret; + + T100 = mxt_get_object(data, MXT_TOUCH_MULTITOUCHSCREEN_T100); + if (!T100) + return -EINVAL; + + /* Get SRCAUX Setting */ + ret = __mxt_read_reg(client, T100->start_address + MXT_T100_SCRAUX, + 1, &srcaux); + if (ret) + return ret; + data->T100_enabled_num_reportable_touches = + (srcaux & MXT_T100_SRCAUX_NUMRPTTCH); + data->T100_enabled_touch_area = (srcaux & MXT_T100_SRCAUX_TCHAREA); + data->T100_enabled_antitouch_area = (srcaux & MXT_T100_SRCAUX_ATCHAREA); + data->T100_enabled_internal_tracking_area = + (srcaux & MXT_T100_SRCAUX_INTTHRAREA); + + /* Get TCHAUX Setting */ + ret = __mxt_read_reg(client, T100->start_address + MXT_T100_TCHAUX, + 1, &tchaux); + if (ret) + return ret; + data->T100_enabled_vector = (tchaux & MXT_T100_TCHAUX_VECT); + data->T100_enabled_amplitude = (tchaux & MXT_T100_TCHAUX_AMPL); + data->T100_enabled_area = (tchaux & MXT_T100_TCHAUX_AREA); + data->T100_enabled_peak = (tchaux & MXT_T100_TCHAUX_PEAK); + + dev_info(&client->dev, "T100 Config: SCRAUX : %X, TCHAUX : %X", + srcaux, tchaux); + + return 0; +} + +static int mxt_calc_resolution_T100(struct mxt_data *data) +{ + struct i2c_client *client = data->client; + u8 orient; + __le16 xyrange[2]; + unsigned int max_x, max_y; + u8 xylines[2]; + int ret; + + struct mxt_object *T100 = mxt_get_object( + data, MXT_TOUCH_MULTITOUCHSCREEN_T100); + if (!T100) + return -EINVAL; + + /* Get touchscreen resolution */ + ret = __mxt_read_reg(client, T100->start_address + MXT_T100_XRANGE, + 2, &xyrange[0]); + if (ret) + return ret; + + ret = __mxt_read_reg(client, T100->start_address + MXT_T100_YRANGE, + 2, &xyrange[1]); + if (ret) + return ret; + + ret = __mxt_read_reg(client, T100->start_address + MXT_T100_CFG1, + 1, &orient); + if (ret) + return ret; + + ret = __mxt_read_reg(client, T100->start_address + MXT_T100_XSIZE, + 1, &xylines[0]); + if (ret) + return ret; + + ret = __mxt_read_reg(client, T100->start_address + MXT_T100_YSIZE, + 1, &xylines[1]); + if (ret) + return ret; + + /* TODO: Read the TCHAUX field and save the VECT/AMPL/AREA config. */ + + max_x = le16_to_cpu(xyrange[0]); + max_y = le16_to_cpu(xyrange[1]); + + if (max_x == 0) + max_x = 1023; + + if (max_y == 0) + max_y = 1023; + + if (orient & MXT_T100_CFG_SWITCHXY) { + data->max_x = max_y; + data->max_y = max_x; + } else { + data->max_x = max_x; + data->max_y = max_y; + } + + data->max_area_pixels = max_x * max_y; + data->max_area_channels = xylines[0] * xylines[1]; + + dev_info(&client->dev, + "T100 Config: XSIZE %u, YSIZE %u, XLINE %u, YLINE %u", + max_x, max_y, xylines[0], xylines[1]); + + return 0; +} + +static int mxt_calc_resolution_T9(struct mxt_data *data) +{ + struct i2c_client *client = data->client; + u8 orient; + __le16 xyrange[2]; + unsigned int max_x, max_y; + u8 xylines[2]; + int ret; + + struct mxt_object *T9 = mxt_get_object(data, MXT_TOUCH_MULTI_T9); + if (T9 == NULL) + return -EINVAL; + + /* Get touchscreen resolution */ + ret = __mxt_read_reg(client, T9->start_address + MXT_T9_XRANGE_LSB, + 4, xyrange); + if (ret) + return ret; + + ret = __mxt_read_reg(client, T9->start_address + MXT_T9_ORIENT, + 1, &orient); + if (ret) + return ret; + + ret = __mxt_read_reg(client, T9->start_address + MXT_T9_XSIZE, + 2, xylines); + if (ret) + return ret; + + max_x = le16_to_cpu(xyrange[0]); + max_y = le16_to_cpu(xyrange[1]); + + if (orient & MXT_XY_SWITCH) { + data->max_x = max_y; + data->max_y = max_x; + } else { + data->max_x = max_x; + data->max_y = max_y; + } + + data->max_area_pixels = max_x * max_y; + data->max_area_channels = xylines[0] * xylines[1]; + + dev_info(&client->dev, + "T9 Config: XSIZE %u, YSIZE %u, XLINE %u, YLINE %u", + max_x, max_y, xylines[0], xylines[1]); + + return 0; +} + +/* + * Atmel Raw Config File Format + * + * The first four lines of the raw config file contain: + * 1) Version + * 2) Chip ID Information (first 7 bytes of device memory) + * 3) Chip Information Block 24-bit CRC Checksum + * 4) Chip Configuration 24-bit CRC Checksum + * + * The rest of the file consists of one line per object instance: + * + * + * - 2-byte object type as hex + * - 2-byte object instance number as hex + * - 2-byte object size as hex + * - array of 1-byte hex values + */ +static int mxt_cfg_verify_hdr(struct mxt_data *data, char **config) +{ + struct i2c_client *client = data->client; + struct device *dev = &client->dev; + struct mxt_info info; + char *token; + int ret = 0; + u32 crc; + + /* Process the first four lines of the file*/ + /* 1) Version */ + token = strsep(config, "\n"); + dev_info(dev, "Config File: Version = %s\n", token ?: ""); + if (!token || + strncmp(token, MXT_CFG_MAGIC, strlen(MXT_CFG_MAGIC))) { + dev_err(dev, "Invalid config file: Bad Version\n"); + return -EINVAL; + } + + /* 2) Chip ID */ + token = strsep(config, "\n"); + if (!token) { + dev_err(dev, "Invalid config file: No Chip ID\n"); + return -EINVAL; + } + ret = sscanf(token, "%hhx %hhx %hhx %hhx %hhx %hhx %hhx", + &info.family_id, &info.variant_id, + &info.version, &info.build, &info.matrix_xsize, + &info.matrix_ysize, &info.object_num); + dev_info(dev, "Config File: Chip ID = %02x %02x %02x %02x %02x %02x %02x\n", + info.family_id, info.variant_id, info.version, info.build, + info.matrix_xsize, info.matrix_ysize, info.object_num); + if (ret != 7 || + info.family_id != data->info.family_id || + info.variant_id != data->info.variant_id || + info.version != data->info.version || + info.build != data->info.build || + info.object_num != data->info.object_num) { + dev_err(dev, "Invalid config file: Chip ID info mismatch\n"); + dev_err(dev, "Chip Info: %02x %02x %02x %02x %02x %02x %02x\n", + data->info.family_id, data->info.variant_id, + data->info.version, data->info.build, + data->info.matrix_xsize, data->info.matrix_ysize, + data->info.object_num); + return -EINVAL; + } + + /* 3) Info Block CRC */ + token = strsep(config, "\n"); + if (!token) { + dev_err(dev, "Invalid config file: No Info Block CRC\n"); + return -EINVAL; + } + + if (info.matrix_xsize != data->info.matrix_xsize || + info.matrix_ysize != data->info.matrix_ysize) { + /* + * Matrix xsize and ysize depend on the state of T46 byte 1 + * for the XY Mode. A mismatch is possible due to + * a corrupted register set. The config update should proceed + * to correct the problem. In this condition, the info block + * CRC check should be skipped. + */ + dev_info(dev, "Matrix Xsize and Ysize mismatch. Updating.\n"); + dev_info(dev, "Chip Info: %02x %02x %02x %02x %02x %02x %02x\n", + data->info.family_id, data->info.variant_id, + data->info.version, data->info.build, + data->info.matrix_xsize, data->info.matrix_ysize, + data->info.object_num); + goto config_crc; + } + + ret = sscanf(token, "%x", &crc); + if (ret != 1 || crc != data->info_crc) { + dev_err(dev, "Config File: Info Block info_csum: %06x != %06x\n", + crc, data->info_crc); + dev_err(dev, "Invalid config file: Bad Info Block CRC\n"); + return -EINVAL; + } + +config_crc: + /* 4) Config CRC */ + /* + * Parse but don't verify against current config; + * TODO: Verify against CRC of rest of file? + */ + token = strsep(config, "\n"); + if (!token) { + dev_err(dev, "Invalid config file: No Config CRC\n"); + return -EINVAL; + } + ret = sscanf(token, "%x", &crc); + dev_info(dev, "Config File: Config CRC = %06x\n", crc); + if (ret != 1) { + dev_err(dev, "Invalid config file: Bad Config CRC\n"); + return -EINVAL; + } + + return 0; +} + +static int mxt_cfg_proc_line(struct mxt_data *data, const char *line, + struct list_head *cfg_list) +{ + struct i2c_client *client = data->client; + struct device *dev = &client->dev; + int ret; + u16 type, instance, size; + int len; + struct mxt_cfg_file_line *cfg_line; + struct mxt_object *object; + u8 *content; + size_t i; + + ret = sscanf(line, "%hx %hx %hx%n", &type, &instance, &size, &len); + /* Skip unparseable lines */ + if (ret < 3) + return 0; + /* Only support 1-byte types */ + if (type > 0xff) { + dev_err(dev, "Invalid type = %X\n", type); + return -EINVAL; + } + + /* Supplied object MUST be a valid instance and match object size */ + object = mxt_get_object(data, type); + if (!object) { + dev_err(dev, "Can't get object\n"); + return -EINVAL; + } + + if (instance > mxt_obj_instances(object)) { + dev_err(dev, "Too many instances. Type=%x (%u > %zu)\n", + type, instance, mxt_obj_instances(object)); + return -EINVAL; + } + + if (size != mxt_obj_size(object)) { + dev_err(dev, "Incorrect obect size. Type=%x (%u != %zu)\n", + type, size, mxt_obj_size(object)); + return -EINVAL; + } + + content = kmalloc(size, GFP_KERNEL); + if (!content) + return -ENOMEM; + + for (i = 0; i < size; i++) { + line += len; + ret = sscanf(line, "%hhx%n", &content[i], &len); + if (ret < 1) { + ret = -EINVAL; + goto free_content; + } + } + + cfg_line = kzalloc(sizeof(*cfg_line), GFP_KERNEL); + if (!cfg_line) { + ret = -ENOMEM; + goto free_content; + } + INIT_LIST_HEAD(&cfg_line->list); + cfg_line->addr = object->start_address + + instance * mxt_obj_size(object); + cfg_line->size = mxt_obj_size(object); + cfg_line->content = content; + list_add_tail(&cfg_line->list, cfg_list); + + return 0; + +free_content: + kfree(content); + return ret; +} + +static int mxt_cfg_proc_data(struct mxt_data *data, char **config) +{ + struct i2c_client *client = data->client; + struct device *dev = &client->dev; + char *line; + int ret = 0; + struct list_head cfg_lines; + struct mxt_cfg_file_line *cfg_line, *cfg_line_tmp; + + INIT_LIST_HEAD(&cfg_lines); + + while ((line = strsep(config, "\n"))) { + ret = mxt_cfg_proc_line(data, line, &cfg_lines); + if (ret < 0) + goto free_objects; + } + + list_for_each_entry(cfg_line, &cfg_lines, list) { + dev_dbg(dev, "Addr = %u Size = %u\n", + cfg_line->addr, cfg_line->size); + print_hex_dump(KERN_DEBUG, "atmel_mxt_ts: ", DUMP_PREFIX_OFFSET, + 16, 1, cfg_line->content, cfg_line->size, false); + + ret = __mxt_write_reg(client, cfg_line->addr, cfg_line->size, + cfg_line->content); + if (ret) + break; + } + +free_objects: + list_for_each_entry_safe(cfg_line, cfg_line_tmp, &cfg_lines, list) { + list_del(&cfg_line->list); + kfree(cfg_line->content); + kfree(cfg_line); + } + return ret; +} + +static int mxt_load_config(struct mxt_data *data, const struct firmware *fw) +{ + struct device *dev = &data->client->dev; + int ret, ret2; + char *cfg_copy = NULL; + char *running; + + ret = mutex_lock_interruptible(&data->fw_mutex); + if (ret) + return ret; + + /* Make a mutable, '\0'-terminated copy of the config file */ + cfg_copy = kmalloc(fw->size + 1, GFP_KERNEL); + if (!cfg_copy) { + ret = -ENOMEM; + goto err_alloc_copy; + } + memcpy(cfg_copy, fw->data, fw->size); + cfg_copy[fw->size] = '\0'; + + /* Verify config file header (after which running points to data) */ + running = cfg_copy; + ret = mxt_cfg_verify_hdr(data, &running); + if (ret) { + dev_err(dev, "Error verifying config header (%d)\n", ret); + goto free_cfg_copy; + } + + disable_irq(data->irq); + + if (data->input_dev) { + input_unregister_device(data->input_dev); + data->input_dev = NULL; + } + + /* Write configuration */ + ret = mxt_cfg_proc_data(data, &running); + if (ret) { + dev_err(dev, "Error writing config file (%d)\n", ret); + goto register_input_dev; + } + + /* Backup nvram */ + ret = mxt_write_object(data, MXT_GEN_COMMAND_T6, + MXT_COMMAND_BACKUPNV, + MXT_BACKUP_VALUE); + if (ret) { + dev_err(dev, "Error backup to nvram (%d)\n", ret); + goto register_input_dev; + } + msleep(MXT_BACKUP_TIME); + + /* Reset device */ + ret = mxt_write_object(data, MXT_GEN_COMMAND_T6, + MXT_COMMAND_RESET, 1); + if (ret) { + dev_err(dev, "Error resetting device (%d)\n", ret); + goto register_input_dev; + } + msleep(MXT_RESET_TIME); + + mxt_save_power_config(data); + mxt_save_aux_regs(data); + mxt_stop(data); + +register_input_dev: + ret2 = mxt_get_config_from_chip(data); + if (ret2) { + dev_err(dev, "Failed to fetch config from chip (%d)\n", ret2); + ret = ret2; + } + + ret2 = mxt_initialize_input_device(data); + if (ret2) { + dev_err(dev, "Error creating input_dev (%d)\n", ret2); + ret = ret2; + } + + /* Clear message buffer */ + ret2 = mxt_process_messages_until_invalid(data); + if (ret2) { + dev_err(dev, "Error clearing msg buffer (%d)\n", ret2); + ret = ret2; + } + + enable_irq(data->irq); +free_cfg_copy: + kfree(cfg_copy); +err_alloc_copy: + mutex_unlock(&data->fw_mutex); + return ret; +} + static int mxt_update_file_name(struct device *dev, char **file_name, const char *buf, size_t count) { @@ -2896,6 +3512,35 @@ static ssize_t mxt_object_show(struct device *dev, return error ?: count; } +static ssize_t mxt_update_config_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct mxt_data *data = i2c_get_clientdata(client); + const struct firmware *fw; + int error; + + error = request_firmware(&fw, data->config_file, dev); + if (error) { + dev_err(dev, "Unable to open config file %s, %d\n", + data->config_file, error); + return error; + } + + dev_info(dev, "Using config file %s (size = %zu)\n", + data->config_file, fw->size); + + error = mxt_load_config(data, fw); + if (error) + dev_err(dev, "The config update failed (%d)\n", error); + else + dev_dbg(dev, "The config update succeeded\n"); + + release_firmware(fw); + return error ?: count; +} + static int mxt_check_firmware_format(struct device *dev, const struct firmware *fw) { @@ -3075,6 +3720,7 @@ static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL); static DEVICE_ATTR(info_csum, S_IRUGO, mxt_info_csum_show, NULL); static DEVICE_ATTR(matrix_size, S_IRUGO, mxt_matrix_size_show, NULL); static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL); +static DEVICE_ATTR(update_config, S_IWUSR, NULL, mxt_update_config_store); static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store); static struct attribute *mxt_attrs[] = { @@ -3088,6 +3734,7 @@ static struct attribute *mxt_attrs[] = { &dev_attr_info_csum.attr, &dev_attr_matrix_size.attr, &dev_attr_object.attr, + &dev_attr_update_config.attr, &dev_attr_update_fw.attr, NULL }; @@ -3202,6 +3849,25 @@ static const struct dmi_system_id chromebook_T9_suspend_dmi[] = { { } }; +static int mxt_get_config_from_chip(struct mxt_data *data) +{ + int error; + + error = data->has_T9 ? mxt_calc_resolution_T9(data) : + mxt_calc_resolution_T100(data); + if (error) + return error; + + /* Update T100 settings */ + if (data->has_T100) { + error = mxt_update_setting_T100(data); + if (error) + return error; + } + + return 0; +} + static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct mxt_data *data; @@ -3243,6 +3909,8 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) data->irq = client->irq; i2c_set_clientdata(client, data); + mutex_init(&data->fw_mutex); + init_completion(&data->bl_completion); init_completion(&data->reset_completion); init_completion(&data->crc_completion);