[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20250923144622.2858165-1-dario.binacchi@amarulasolutions.com>
Date: Tue, 23 Sep 2025 16:46:11 +0200
From: Dario Binacchi <dario.binacchi@...rulasolutions.com>
To: linux-kernel@...r.kernel.org
Cc: linux-amarula@...rulasolutions.com,
Dario Binacchi <dario.binacchi@...rulasolutions.com>,
Al Viro <viro@...iv.linux.org.uk>,
Dmitry Torokhov <dmitry.torokhov@...il.com>,
Jens Reidel <adrian@...nlining.org>,
Oliver Graute <oliver.graute@...oconnector.com>,
Wolfram Sang <wsa+renesas@...g-engineering.com>,
Yu Jiaoliang <yujiaoliang@...o.com>,
linux-input@...r.kernel.org
Subject: [PATCH v2] Input: edt-ft5x06 - fix report rate handling by sysfs
In the driver probe, the report-rate-hz value from device tree is written
directly to the M12 controller register, while for the M06 it is divided
by 10 since the controller expects the value in units of 10 Hz. That logic
was missing in the sysfs handling, leading to inconsistent behavior
depending on whether the value came from device tree or sysfs.
This patch makes the report-rate handling consistent by applying the same
logic in both cases. Two dedicated functions, report_rate_hz_{show,store},
were added for the following reasons:
- Avoid modifying the more generic edt_ft5x06_setting_{show,store} and
thus prevent regressions.
- Properly enforce lower and upper limits for the M06 case. The previous
version accepted invalid values for M06, since it relied on the M12
limits.
- Return an error when the property is not supported (e.g. M09), to avoid
misleading users into thinking the property is handled by the
controller.
Signed-off-by: Dario Binacchi <dario.binacchi@...rulasolutions.com>
---
Changes in v2:
- Drop the patch:
1/2 Input: edt-ft5x06 - rename sysfs attribute report_rate to report_rate_hz
because not accepted.
drivers/input/touchscreen/edt-ft5x06.c | 158 +++++++++++++++++++++----
1 file changed, 135 insertions(+), 23 deletions(-)
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index bf498bd4dea9..d7a269a0528f 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -516,9 +516,136 @@ static EDT_ATTR(offset_y, S_IWUSR | S_IRUGO, NO_REGISTER, NO_REGISTER,
/* m06: range 20 to 80, m09: range 0 to 30, m12: range 1 to 255... */
static EDT_ATTR(threshold, S_IWUSR | S_IRUGO, WORK_REGISTER_THRESHOLD,
M09_REGISTER_THRESHOLD, EV_REGISTER_THRESHOLD, 0, 255);
-/* m06: range 3 to 14, m12: range 1 to 255 */
-static EDT_ATTR(report_rate, S_IWUSR | S_IRUGO, WORK_REGISTER_REPORT_RATE,
- M12_REGISTER_REPORT_RATE, NO_REGISTER, 0, 255);
+
+static int edt_ft5x06_report_rate_get(struct edt_ft5x06_ts_data *tsdata)
+{
+ unsigned int val;
+ int error;
+
+ if (tsdata->reg_addr.reg_report_rate == NO_REGISTER)
+ return -EOPNOTSUPP;
+
+ error = regmap_read(tsdata->regmap, tsdata->reg_addr.reg_report_rate,
+ &val);
+ if (error)
+ return error;
+
+ if (tsdata->version == EDT_M06)
+ val *= 10;
+
+ if (val != tsdata->report_rate) {
+ dev_warn(&tsdata->client->dev,
+ "report-rate: read (%d) and stored value (%d) differ\n",
+ val, tsdata->report_rate);
+ tsdata->report_rate = val;
+ }
+
+ return 0;
+}
+
+static ssize_t report_rate_show(struct device *dev,
+ struct device_attribute *dattr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
+ size_t count;
+ int error;
+
+ mutex_lock(&tsdata->mutex);
+
+ if (tsdata->factory_mode) {
+ error = -EIO;
+ goto out;
+ }
+
+ error = edt_ft5x06_report_rate_get(tsdata);
+ if (error) {
+ dev_err(&tsdata->client->dev,
+ "Failed to fetch attribute %s, error %d\n",
+ dattr->attr.name, error);
+ goto out;
+ }
+
+ count = sysfs_emit(buf, "%d\n", tsdata->report_rate);
+out:
+ mutex_unlock(&tsdata->mutex);
+ return error ?: count;
+}
+
+static int edt_ft5x06_report_rate_set(struct edt_ft5x06_ts_data *tsdata,
+ unsigned int val)
+{
+ if (tsdata->reg_addr.reg_report_rate == NO_REGISTER)
+ return -EOPNOTSUPP;
+
+ if (tsdata->version == EDT_M06)
+ tsdata->report_rate = clamp_val(val, 30, 140);
+ else
+ tsdata->report_rate = clamp_val(val, 1, 255);
+
+ if (val != tsdata->report_rate) {
+ dev_warn(&tsdata->client->dev,
+ "report-rate %dHz is unsupported, use %dHz\n",
+ val, tsdata->report_rate);
+ val = tsdata->report_rate;
+ }
+
+ if (tsdata->version == EDT_M06)
+ val /= 10;
+
+ return regmap_write(tsdata->regmap, tsdata->reg_addr.reg_report_rate,
+ val);
+}
+
+static ssize_t report_rate_store(struct device *dev,
+ struct device_attribute *dattr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
+ unsigned int val;
+ u8 limit_low;
+ u8 limit_high;
+ int error;
+
+ mutex_lock(&tsdata->mutex);
+
+ if (tsdata->factory_mode) {
+ error = -EIO;
+ goto out;
+ }
+
+ error = kstrtouint(buf, 0, &val);
+ if (error)
+ goto out;
+
+ if (tsdata->version == EDT_M06) {
+ limit_low = 30;
+ limit_high = 140;
+ } else {
+ limit_low = 1;
+ limit_high = 255;
+ }
+
+ if (val < limit_low || val > limit_high) {
+ error = -ERANGE;
+ goto out;
+ }
+
+ error = edt_ft5x06_report_rate_set(tsdata, val);
+ if (error) {
+ dev_err(&tsdata->client->dev,
+ "Failed to update attribute %s, error: %d\n",
+ dattr->attr.name, error);
+ goto out;
+ }
+
+out:
+ mutex_unlock(&tsdata->mutex);
+ return error ?: count;
+}
+
+static DEVICE_ATTR_RW(report_rate);
static ssize_t model_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -572,7 +699,7 @@ static struct attribute *edt_ft5x06_attrs[] = {
&edt_ft5x06_attr_offset_x.dattr.attr,
&edt_ft5x06_attr_offset_y.dattr.attr,
&edt_ft5x06_attr_threshold.dattr.attr,
- &edt_ft5x06_attr_report_rate.dattr.attr,
+ &dev_attr_report_rate.attr,
&dev_attr_model.attr,
&dev_attr_fw_version.attr,
&dev_attr_header_errors.attr,
@@ -595,8 +722,7 @@ static void edt_ft5x06_restore_reg_parameters(struct edt_ft5x06_ts_data *tsdata)
if (reg_addr->reg_offset_y != NO_REGISTER)
regmap_write(regmap, reg_addr->reg_offset_y, tsdata->offset_y);
if (reg_addr->reg_report_rate != NO_REGISTER)
- regmap_write(regmap, reg_addr->reg_report_rate,
- tsdata->report_rate);
+ edt_ft5x06_report_rate_set(tsdata, tsdata->report_rate);
}
#ifdef CONFIG_DEBUG_FS
@@ -1029,8 +1155,8 @@ static void edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata)
if (reg_addr->reg_offset_y != NO_REGISTER)
regmap_read(regmap, reg_addr->reg_offset_y, &tsdata->offset_y);
if (reg_addr->reg_report_rate != NO_REGISTER)
- regmap_read(regmap, reg_addr->reg_report_rate,
- &tsdata->report_rate);
+ edt_ft5x06_report_rate_get(tsdata);
+
tsdata->num_x = EDT_DEFAULT_NUM_X;
if (reg_addr->reg_num_x != NO_REGISTER) {
if (!regmap_read(regmap, reg_addr->reg_num_x, &val))
@@ -1289,21 +1415,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client)
if (tsdata->reg_addr.reg_report_rate != NO_REGISTER &&
!device_property_read_u32(&client->dev,
"report-rate-hz", &report_rate)) {
- if (tsdata->version == EDT_M06)
- tsdata->report_rate = clamp_val(report_rate, 30, 140);
- else
- tsdata->report_rate = clamp_val(report_rate, 1, 255);
-
- if (report_rate != tsdata->report_rate)
- dev_warn(&client->dev,
- "report-rate %dHz is unsupported, use %dHz\n",
- report_rate, tsdata->report_rate);
-
- if (tsdata->version == EDT_M06)
- tsdata->report_rate /= 10;
-
- regmap_write(tsdata->regmap, tsdata->reg_addr.reg_report_rate,
- tsdata->report_rate);
+ edt_ft5x06_report_rate_set(tsdata, report_rate);
}
dev_dbg(&client->dev,
--
2.43.0
base-commit: f975f08c2e899ae2484407d7bba6bb7f8b6d9d40
branch: edt-ft5x06-report-rate
Powered by blists - more mailing lists