Linux Input Archive on lore.kernel.org
 help / color / Atom feed
* [RFC] input: cap11xx: plasma globe proof
@ 2019-12-29 19:21 Kurt Van Dijck
  2019-12-29 19:21 ` [PATCH 1/6] cap11xx: set device driver_data Kurt Van Dijck
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Kurt Van Dijck @ 2019-12-29 19:21 UTC (permalink / raw)
  To: linux-input; +Cc: linux-can

Hey,

I built a raspberry-pi wakeup for my kids. Recently, one of them bought
a plasma globe. That globe leaves an electrostatic field that disturbes
the cap11xx when it operates with default settings.
So I grabbed the datasheet and started modifying the configuration.
This is the result that should apply to other scenarios as well.

The patch series improves the cap11xx in 2 ways.
It adds support for a cap1208 as on the explorer hat of Pimoroni,
and allows to run in polling mode (the explorer hat omitted the irq,
or I didn't find it).
It then exposes the major configuration parts of the chip so one can
tune it to her/his needs.

Please feel free to comment

Kind regards,
Kurt


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/6] cap11xx: set device driver_data
  2019-12-29 19:21 [RFC] input: cap11xx: plasma globe proof Kurt Van Dijck
@ 2019-12-29 19:21 ` Kurt Van Dijck
  2019-12-29 19:21 ` [PATCH 2/6] cap11xx: support cap1208 Kurt Van Dijck
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Kurt Van Dijck @ 2019-12-29 19:21 UTC (permalink / raw)
  To: linux-input; +Cc: linux-can, Kurt Van Dijck

Signed-off-by: Kurt Van Dijck <dev.kurt@vandijck-laurijssen.be>
---
 drivers/input/keyboard/cap11xx.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c
index 688e2be..16287ab 100644
--- a/drivers/input/keyboard/cap11xx.c
+++ b/drivers/input/keyboard/cap11xx.c
@@ -346,6 +346,8 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client,
 	if (!priv)
 		return -ENOMEM;
 
+	i2c_set_clientdata(i2c_client, priv);
+
 	priv->regmap = devm_regmap_init_i2c(i2c_client, &cap11xx_regmap_config);
 	if (IS_ERR(priv->regmap))
 		return PTR_ERR(priv->regmap);
-- 
1.8.5.rc3


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 2/6] cap11xx: support cap1208
  2019-12-29 19:21 [RFC] input: cap11xx: plasma globe proof Kurt Van Dijck
  2019-12-29 19:21 ` [PATCH 1/6] cap11xx: set device driver_data Kurt Van Dijck
@ 2019-12-29 19:21 ` Kurt Van Dijck
  2019-12-29 19:21 ` [PATCH 3/6] cap11xx: polling mode without irq Kurt Van Dijck
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Kurt Van Dijck @ 2019-12-29 19:21 UTC (permalink / raw)
  To: linux-input; +Cc: linux-can, Kurt Van Dijck

Signed-off-by: Kurt Van Dijck <dev.kurt@vandijck-laurijssen.be>
---
 drivers/input/keyboard/cap11xx.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c
index 16287ab..092dcd2 100644
--- a/drivers/input/keyboard/cap11xx.c
+++ b/drivers/input/keyboard/cap11xx.c
@@ -97,12 +97,14 @@ enum {
 	CAP1106,
 	CAP1126,
 	CAP1188,
+	CAP1208,
 };
 
 static const struct cap11xx_hw_model cap11xx_devices[] = {
 	[CAP1106] = { .product_id = 0x55, .num_channels = 6, .num_leds = 0 },
 	[CAP1126] = { .product_id = 0x53, .num_channels = 6, .num_leds = 2 },
 	[CAP1188] = { .product_id = 0x50, .num_channels = 8, .num_leds = 8 },
+	[CAP1208] = { .product_id = 0x6b, .num_channels = 8, .num_leds = 0 },
 };
 
 static const struct reg_default cap11xx_reg_defaults[] = {
@@ -472,6 +474,7 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client,
 	{ .compatible = "microchip,cap1106", },
 	{ .compatible = "microchip,cap1126", },
 	{ .compatible = "microchip,cap1188", },
+	{ .compatible = "microchip,cap1208", },
 	{}
 };
 MODULE_DEVICE_TABLE(of, cap11xx_dt_ids);
@@ -480,6 +483,7 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client,
 	{ "cap1106", CAP1106 },
 	{ "cap1126", CAP1126 },
 	{ "cap1188", CAP1188 },
+	{ "cap1208", CAP1208 },
 	{}
 };
 MODULE_DEVICE_TABLE(i2c, cap11xx_i2c_ids);
-- 
1.8.5.rc3


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 3/6] cap11xx: polling mode without irq
  2019-12-29 19:21 [RFC] input: cap11xx: plasma globe proof Kurt Van Dijck
  2019-12-29 19:21 ` [PATCH 1/6] cap11xx: set device driver_data Kurt Van Dijck
  2019-12-29 19:21 ` [PATCH 2/6] cap11xx: support cap1208 Kurt Van Dijck
@ 2019-12-29 19:21 ` Kurt Van Dijck
  2019-12-29 19:21 ` [PATCH 4/6] cap11xx: add register definition for LED_LINK Kurt Van Dijck
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Kurt Van Dijck @ 2019-12-29 19:21 UTC (permalink / raw)
  To: linux-input; +Cc: linux-can, Kurt Van Dijck

Signed-off-by: Kurt Van Dijck <dev.kurt@vandijck-laurijssen.be>
---
 drivers/input/keyboard/cap11xx.c | 49 ++++++++++++++++++++++++++++++++++++----
 1 file changed, 45 insertions(+), 4 deletions(-)

diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c
index 092dcd2..5a7eaed 100644
--- a/drivers/input/keyboard/cap11xx.c
+++ b/drivers/input/keyboard/cap11xx.c
@@ -9,6 +9,7 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/input.h>
+#include <linux/kthread.h>
 #include <linux/leds.h>
 #include <linux/of_irq.h>
 #include <linux/regmap.h>
@@ -78,6 +79,7 @@ struct cap11xx_led {
 
 struct cap11xx_priv {
 	struct regmap *regmap;
+	struct task_struct *poll_thread;
 	struct input_dev *idev;
 
 	struct cap11xx_led *leds;
@@ -202,6 +204,24 @@ static irqreturn_t cap11xx_thread_func(int irq_num, void *data)
 	return IRQ_HANDLED;
 }
 
+static int poll_irq(void *data) {
+
+	struct cap11xx_priv *priv = data;
+	int ret;
+	unsigned int status;
+
+	/* until module unload */
+	while (!kthread_should_stop()) {
+		ret = regmap_read(priv->regmap, CAP11XX_REG_MAIN_CONTROL, &status);
+		if (ret >= 0 && (status & 1))
+			cap11xx_thread_func(-1, priv);
+		usleep_range(15000, 25000);
+	}
+
+	return 0;
+}
+
+
 static int cap11xx_set_sleep(struct cap11xx_priv *priv, bool sleep)
 {
 	/*
@@ -320,6 +340,17 @@ static int cap11xx_init_leds(struct device *dev,
 }
 #endif
 
+static int cap11xx_i2c_remove(struct i2c_client *i2c_client)
+{
+	struct cap11xx_priv *priv = i2c_get_clientdata(i2c_client);
+
+	if (priv->poll_thread) {
+		kthread_stop(priv->poll_thread);
+		mdelay(10);
+	}
+	return 0;
+}
+
 static int cap11xx_i2c_probe(struct i2c_client *i2c_client,
 			     const struct i2c_device_id *id)
 {
@@ -348,8 +379,6 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client,
 	if (!priv)
 		return -ENOMEM;
 
-	i2c_set_clientdata(i2c_client, priv);
-
 	priv->regmap = devm_regmap_init_i2c(i2c_client, &cap11xx_regmap_config);
 	if (IS_ERR(priv->regmap))
 		return PTR_ERR(priv->regmap);
@@ -458,8 +487,19 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client,
 
 	irq = irq_of_parse_and_map(node, 0);
 	if (!irq) {
-		dev_err(dev, "Unable to parse or map IRQ\n");
-		return -ENXIO;
+		if (!of_property_read_bool(node, "linux,irq-poll")) {
+			dev_err(dev, "Unable to parse or map IRQ\n");
+			return -ENXIO;
+		}
+		dev_info(dev, "IRQ failed or undefined, using poll_thread\n");
+		priv->poll_thread = kthread_create(poll_irq, priv, "%s-%s-poll",
+				id->name, dev_name(dev));
+		if (!priv->poll_thread) {
+			dev_err(dev, "Unable to start poll_thread\n");
+			return -ENXIO;
+		}
+		wake_up_process(priv->poll_thread);
+		return 0;
 	}
 
 	error = devm_request_threaded_irq(dev, irq, NULL, cap11xx_thread_func,
@@ -495,6 +535,7 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client,
 	},
 	.id_table	= cap11xx_i2c_ids,
 	.probe		= cap11xx_i2c_probe,
+	.remove		= cap11xx_i2c_remove,
 };
 
 module_i2c_driver(cap11xx_i2c_driver);
-- 
1.8.5.rc3


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 4/6] cap11xx: add register definition for LED_LINK
  2019-12-29 19:21 [RFC] input: cap11xx: plasma globe proof Kurt Van Dijck
                   ` (2 preceding siblings ...)
  2019-12-29 19:21 ` [PATCH 3/6] cap11xx: polling mode without irq Kurt Van Dijck
@ 2019-12-29 19:21 ` Kurt Van Dijck
  2019-12-29 19:21 ` [PATCH 5/6] cap11xx: enable all 8 inputs Kurt Van Dijck
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Kurt Van Dijck @ 2019-12-29 19:21 UTC (permalink / raw)
  To: linux-input; +Cc: linux-can, Kurt Van Dijck

Signed-off-by: Kurt Van Dijck <dev.kurt@vandijck-laurijssen.be>
---
 drivers/input/keyboard/cap11xx.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c
index 5a7eaed..b666e9e 100644
--- a/drivers/input/keyboard/cap11xx.c
+++ b/drivers/input/keyboard/cap11xx.c
@@ -46,6 +46,7 @@
 #define CAP11XX_REG_CONFIG2		0x44
 #define CAP11XX_REG_CONFIG2_ALT_POL	BIT(6)
 #define CAP11XX_REG_SENSOR_BASE_CNT(X)	(0x50 + (X))
+#define CAP11XX_REG_SENSOR_LED_LINK	0x72
 #define CAP11XX_REG_LED_POLARITY	0x73
 #define CAP11XX_REG_LED_OUTPUT_CONTROL	0x74
 
@@ -139,6 +140,7 @@ enum {
 	{ CAP11XX_REG_STANDBY_SENSITIVITY,	0x02 },
 	{ CAP11XX_REG_STANDBY_THRESH,		0x40 },
 	{ CAP11XX_REG_CONFIG2,			0x40 },
+	{ CAP11XX_REG_SENSOR_LED_LINK,		0x00 },
 	{ CAP11XX_REG_LED_POLARITY,		0x00 },
 	{ CAP11XX_REG_SENSOR_CALIB_LSB1,	0x00 },
 	{ CAP11XX_REG_SENSOR_CALIB_LSB2,	0x00 },
-- 
1.8.5.rc3


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 5/6] cap11xx: enable all 8 inputs
  2019-12-29 19:21 [RFC] input: cap11xx: plasma globe proof Kurt Van Dijck
                   ` (3 preceding siblings ...)
  2019-12-29 19:21 ` [PATCH 4/6] cap11xx: add register definition for LED_LINK Kurt Van Dijck
@ 2019-12-29 19:21 ` Kurt Van Dijck
  2019-12-29 19:21 ` [PATCH 6/6] cap11xx: export major chip settings to sysfs Kurt Van Dijck
  2020-01-09 20:03 ` [RFC] input: cap11xx: plasma globe proof Kurt Van Dijck
  6 siblings, 0 replies; 8+ messages in thread
From: Kurt Van Dijck @ 2019-12-29 19:21 UTC (permalink / raw)
  To: linux-input; +Cc: linux-can, Kurt Van Dijck

Signed-off-by: Kurt Van Dijck <dev.kurt@vandijck-laurijssen.be>
---
 drivers/input/keyboard/cap11xx.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c
index b666e9e..cdcc89b9 100644
--- a/drivers/input/keyboard/cap11xx.c
+++ b/drivers/input/keyboard/cap11xx.c
@@ -117,13 +117,13 @@ enum {
 	{ CAP11XX_REG_NOISE_FLAG_STATUS,	0x00 },
 	{ CAP11XX_REG_SENSITIVITY_CONTROL,	0x2f },
 	{ CAP11XX_REG_CONFIG,			0x20 },
-	{ CAP11XX_REG_SENSOR_ENABLE,		0x3f },
+	{ CAP11XX_REG_SENSOR_ENABLE,		0xff },
 	{ CAP11XX_REG_SENSOR_CONFIG,		0xa4 },
 	{ CAP11XX_REG_SENSOR_CONFIG2,		0x07 },
 	{ CAP11XX_REG_SAMPLING_CONFIG,		0x39 },
 	{ CAP11XX_REG_CALIBRATION,		0x00 },
-	{ CAP11XX_REG_INT_ENABLE,		0x3f },
-	{ CAP11XX_REG_REPEAT_RATE,		0x3f },
+	{ CAP11XX_REG_INT_ENABLE,		0xff },
+	{ CAP11XX_REG_REPEAT_RATE,		0xff },
 	{ CAP11XX_REG_MT_CONFIG,		0x80 },
 	{ CAP11XX_REG_MT_PATTERN_CONFIG,	0x00 },
 	{ CAP11XX_REG_MT_PATTERN,		0x3f },
@@ -134,6 +134,8 @@ enum {
 	{ CAP11XX_REG_SENSOR_THRESH(3),		0x40 },
 	{ CAP11XX_REG_SENSOR_THRESH(4),		0x40 },
 	{ CAP11XX_REG_SENSOR_THRESH(5),		0x40 },
+	{ CAP11XX_REG_SENSOR_THRESH(6),		0x40 },
+	{ CAP11XX_REG_SENSOR_THRESH(7),		0x40 },
 	{ CAP11XX_REG_SENSOR_NOISE_THRESH,	0x01 },
 	{ CAP11XX_REG_STANDBY_CHANNEL,		0x00 },
 	{ CAP11XX_REG_STANDBY_CONFIG,		0x39 },
@@ -157,6 +159,8 @@ static bool cap11xx_volatile_reg(struct device *dev, unsigned int reg)
 	case CAP11XX_REG_SENOR_DELTA(3):
 	case CAP11XX_REG_SENOR_DELTA(4):
 	case CAP11XX_REG_SENOR_DELTA(5):
+	case CAP11XX_REG_SENOR_DELTA(6):
+	case CAP11XX_REG_SENOR_DELTA(7):
 	case CAP11XX_REG_PRODUCT_ID:
 	case CAP11XX_REG_MANUFACTURER_ID:
 	case CAP11XX_REG_REVISION:
-- 
1.8.5.rc3


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 6/6] cap11xx: export major chip settings to sysfs
  2019-12-29 19:21 [RFC] input: cap11xx: plasma globe proof Kurt Van Dijck
                   ` (4 preceding siblings ...)
  2019-12-29 19:21 ` [PATCH 5/6] cap11xx: enable all 8 inputs Kurt Van Dijck
@ 2019-12-29 19:21 ` Kurt Van Dijck
  2020-01-09 20:03 ` [RFC] input: cap11xx: plasma globe proof Kurt Van Dijck
  6 siblings, 0 replies; 8+ messages in thread
From: Kurt Van Dijck @ 2019-12-29 19:21 UTC (permalink / raw)
  To: linux-input; +Cc: linux-can, Kurt Van Dijck

Signed-off-by: Kurt Van Dijck <dev.kurt@vandijck-laurijssen.be>
---
 drivers/input/keyboard/cap11xx.c | 161 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 161 insertions(+)

diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c
index cdcc89b9..eb68efc 100644
--- a/drivers/input/keyboard/cap11xx.c
+++ b/drivers/input/keyboard/cap11xx.c
@@ -346,6 +346,159 @@ static int cap11xx_init_leds(struct device *dev,
 }
 #endif
 
+/* register attribute:
+ * create a simple way to export properties in the register map
+ */
+struct register_attribute {
+	struct device_attribute dev_attr;
+	int reg;
+	int mask;
+	int shift;
+};
+#define to_reg_attr(_dev_attr) container_of((dev_attr), \
+		struct register_attribute, dev_attr)
+#define to_dev_attr(_attr) container_of(attr, struct device_attribute, attr)
+
+static ssize_t show_reg_attr(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct cap11xx_priv *priv = dev_get_drvdata(dev);
+	struct register_attribute *rattr = to_reg_attr(attr);
+	int ret, value;
+
+	ret = regmap_read(priv->regmap, rattr->reg, &value);
+	if (ret < 0)
+		return ret;
+	return sprintf(buf, "0x%02x\n", (value >> rattr->shift) & rattr->mask);
+}
+
+static ssize_t store_reg_attr(struct device *dev, struct device_attribute * attr,
+		const char *buf, size_t len)
+{
+	struct cap11xx_priv *priv = dev_get_drvdata(dev);
+	struct register_attribute *rattr = to_reg_attr(attr);
+	int ret;
+	long value;
+
+	ret = kstrtoul(buf, 0, &value);
+	if (ret)
+		return ret;
+
+	if (value & ~rattr->mask)
+		return -ERANGE;
+
+	ret = regmap_update_bits(priv->regmap, rattr->reg,
+			rattr->mask << rattr->shift, value << rattr->shift);
+	if (ret)
+		return ret;
+	return len;
+}
+
+#define REG_ATTR(_name, _mode, _reg, _nbits, _shift) \
+	struct register_attribute reg_dev_attr_##_name = { \
+		__ATTR(_name, _mode, show_reg_attr, store_reg_attr), \
+		.reg = _reg, \
+		.mask = (1 << (_nbits)) -1, \
+		.shift = _shift, \
+	}
+#define TO_ATTR(_name) (&(reg_dev_attr_##_name).dev_attr.attr)
+
+static REG_ATTR(gain, 0644, CAP11XX_REG_MAIN_CONTROL, 2, 6);
+static REG_ATTR(delta_sense, 0644, CAP11XX_REG_SENSITIVITY_CONTROL, 3, 4);
+static REG_ATTR(base_shift, 0644, CAP11XX_REG_SENSITIVITY_CONTROL, 4, 0);
+static REG_ATTR(dis_dig_noise, 0644, CAP11XX_REG_CONFIG, 1, 5);
+static REG_ATTR(dis_ana_noise, 0644, CAP11XX_REG_CONFIG, 1, 4);
+static REG_ATTR(max_dur_enable, 0644, CAP11XX_REG_CONFIG, 1, 3);
+static REG_ATTR(cs_en, 0644, CAP11XX_REG_SENSOR_ENABLE, 8, 0);
+static REG_ATTR(max_dur, 0644, CAP11XX_REG_SENSOR_CONFIG, 4, 4);
+static REG_ATTR(avg, 0644, CAP11XX_REG_SAMPLING_CONFIG, 3, 4);
+static REG_ATTR(samp_time, 0644, CAP11XX_REG_SAMPLING_CONFIG, 2, 2);
+static REG_ATTR(cycle_time, 0644, CAP11XX_REG_SAMPLING_CONFIG, 2, 0);
+static REG_ATTR(mulkt_blk_en, 0644, CAP11XX_REG_MT_CONFIG, 1, 7);
+static REG_ATTR(b_mult_t, 0644, CAP11XX_REG_MT_CONFIG, 2, 2);
+static REG_ATTR(mtp_en, 0644, CAP11XX_REG_MT_PATTERN_CONFIG, 1, 7);
+static REG_ATTR(mtp_th, 0644, CAP11XX_REG_MT_PATTERN_CONFIG, 2, 2);
+static REG_ATTR(comp_ptrn, 0644, CAP11XX_REG_MT_PATTERN_CONFIG, 1, 1);
+static REG_ATTR(cs_ptrn, 0644, CAP11XX_REG_MT_PATTERN, 8, 0);
+static REG_ATTR(cs_th1, 0644, CAP11XX_REG_SENSOR_THRESH(0), 8, 0);
+static REG_ATTR(cs_th2, 0644, CAP11XX_REG_SENSOR_THRESH(1), 8, 0);
+static REG_ATTR(cs_th3, 0644, CAP11XX_REG_SENSOR_THRESH(2), 8, 0);
+static REG_ATTR(cs_th4, 0644, CAP11XX_REG_SENSOR_THRESH(3), 8, 0);
+static REG_ATTR(cs_th5, 0644, CAP11XX_REG_SENSOR_THRESH(4), 8, 0);
+static REG_ATTR(cs_th6, 0644, CAP11XX_REG_SENSOR_THRESH(5), 8, 0);
+static REG_ATTR(cs_th7, 0644, CAP11XX_REG_SENSOR_THRESH(6), 8, 0);
+static REG_ATTR(cs_th8, 0644, CAP11XX_REG_SENSOR_THRESH(7), 8, 0);
+static REG_ATTR(cs_bn_th, 0644, CAP11XX_REG_SENSOR_NOISE_THRESH, 2, 0);
+static REG_ATTR(cs_led, 0644, CAP11XX_REG_SENSOR_LED_LINK, 8, 0);
+
+static struct attribute *reg_attrs[] = {
+	TO_ATTR(gain),
+	TO_ATTR(delta_sense),
+	TO_ATTR(base_shift),
+	TO_ATTR(dis_dig_noise),
+	TO_ATTR(dis_ana_noise),
+	TO_ATTR(max_dur_enable),
+	TO_ATTR(cs_en),
+	TO_ATTR(max_dur),
+	TO_ATTR(avg),
+	TO_ATTR(samp_time),
+	TO_ATTR(cycle_time),
+	TO_ATTR(mulkt_blk_en),
+	TO_ATTR(b_mult_t),
+	TO_ATTR(mtp_en),
+	TO_ATTR(mtp_th),
+	TO_ATTR(comp_ptrn),
+	TO_ATTR(cs_ptrn),
+	TO_ATTR(cs_th1),
+	TO_ATTR(cs_th2),
+	TO_ATTR(cs_th3),
+	TO_ATTR(cs_th4),
+	TO_ATTR(cs_th5),
+	TO_ATTR(cs_th6),
+	TO_ATTR(cs_th7),
+	TO_ATTR(cs_th8),
+	TO_ATTR(cs_bn_th),
+	TO_ATTR(cs_led),
+	NULL,
+};
+
+static const struct attribute_group reg_attr_group = {
+	.name = "reg",
+	.attrs = reg_attrs,
+};
+
+/* load register properties from OF */
+static int cap11xx_load_regs_from_of(struct device *dev)
+{
+	struct cap11xx_priv *priv = dev_get_drvdata(dev);
+	struct attribute **attr;
+	struct register_attribute *rattr;
+	char name[32];
+	int ret, value;
+
+	for (attr = reg_attrs; *attr; ++attr) {
+		rattr = to_reg_attr(to_dev_attr(*attr));
+
+		sprintf(name, "reg,%s", rattr->dev_attr.attr.name);
+		ret = of_property_read_u32(dev->of_node, name, &value);
+		if (ret)
+			continue;
+		if (value & ~rattr->mask) {
+			dev_warn(dev, "of %s: value %u, max %u\n",
+					name, value, rattr->mask);
+			continue;
+		}
+		ret = regmap_update_bits(priv->regmap, rattr->reg,
+				rattr->mask << rattr->shift,
+				value << rattr->shift);
+		if (ret) {
+			dev_err(dev, "of %s, regmap returned %i\n", name, ret);
+			return ret;
+		}
+	}
+	return 0;
+}
+
 static int cap11xx_i2c_remove(struct i2c_client *i2c_client)
 {
 	struct cap11xx_priv *priv = i2c_get_clientdata(i2c_client);
@@ -430,6 +583,10 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client,
 			return error;
 	}
 
+	error = cap11xx_load_regs_from_of(dev);
+	if (error)
+		return error;
+
 	/* Provide some useful defaults */
 	for (i = 0; i < cap->num_channels; i++)
 		priv->keycodes[i] = KEY_A + i;
@@ -491,6 +648,10 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client,
 	if (error)
 		return error;
 
+	error = devm_device_add_group(dev, &reg_attr_group);
+	if (error)
+		return error;
+
 	irq = irq_of_parse_and_map(node, 0);
 	if (!irq) {
 		if (!of_property_read_bool(node, "linux,irq-poll")) {
-- 
1.8.5.rc3


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC] input: cap11xx: plasma globe proof
  2019-12-29 19:21 [RFC] input: cap11xx: plasma globe proof Kurt Van Dijck
                   ` (5 preceding siblings ...)
  2019-12-29 19:21 ` [PATCH 6/6] cap11xx: export major chip settings to sysfs Kurt Van Dijck
@ 2020-01-09 20:03 ` Kurt Van Dijck
  6 siblings, 0 replies; 8+ messages in thread
From: Kurt Van Dijck @ 2020-01-09 20:03 UTC (permalink / raw)
  To: linux-input; +Cc: linux-can

Ping?

On zo, 29 dec 2019 20:21:11 +0100, Kurt Van Dijck wrote:
> Hey,
> 
> I built a raspberry-pi wakeup for my kids. Recently, one of them bought
> a plasma globe. That globe leaves an electrostatic field that disturbes
> the cap11xx when it operates with default settings.
> So I grabbed the datasheet and started modifying the configuration.
> This is the result that should apply to other scenarios as well.
> 
> The patch series improves the cap11xx in 2 ways.
> It adds support for a cap1208 as on the explorer hat of Pimoroni,
> and allows to run in polling mode (the explorer hat omitted the irq,
> or I didn't find it).
> It then exposes the major configuration parts of the chip so one can
> tune it to her/his needs.
> 
> Please feel free to comment
> 
> Kind regards,
> Kurt
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, back to index

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-29 19:21 [RFC] input: cap11xx: plasma globe proof Kurt Van Dijck
2019-12-29 19:21 ` [PATCH 1/6] cap11xx: set device driver_data Kurt Van Dijck
2019-12-29 19:21 ` [PATCH 2/6] cap11xx: support cap1208 Kurt Van Dijck
2019-12-29 19:21 ` [PATCH 3/6] cap11xx: polling mode without irq Kurt Van Dijck
2019-12-29 19:21 ` [PATCH 4/6] cap11xx: add register definition for LED_LINK Kurt Van Dijck
2019-12-29 19:21 ` [PATCH 5/6] cap11xx: enable all 8 inputs Kurt Van Dijck
2019-12-29 19:21 ` [PATCH 6/6] cap11xx: export major chip settings to sysfs Kurt Van Dijck
2020-01-09 20:03 ` [RFC] input: cap11xx: plasma globe proof Kurt Van Dijck

Linux Input Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-input/0 linux-input/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-input linux-input/ https://lore.kernel.org/linux-input \
		linux-input@vger.kernel.org
	public-inbox-index linux-input

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-input


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git